Can a RhinoMock mock hold property values? - rhino-mocks

I have been stuck on this for a day or two, I have recently started using RhinoMocks (v3.5)and I have setup a test. A stub web service that returns a List collection and a class that calls it, and a mock object with a property i expect to be set as a result of the call to the web service. My code is like this:
[Test]
public void Call_WebService_list_populated()
{
IData stService = MockRepository.GenerateStub<IData>();
IDefault mockView = MockRepository.GenerateMock<IDefault>();
DefaultPresenter presenter = new DefaultPresenter(mockView);
presenter.StService = stService;
mockView.Stub(x => x.RequestingUser).Return("test");
List<string> testList = new List<string> { new string() };
stService.Stub(x => x.GetList("test")).Return(testList);
presenter.LoadList();
Assert.AreEqual(testList,mockView.List);
}
In the LoadList function it just assigns the List property of mockView the list returned from the webservice. I can get the test to work using this line:
mockView.AssertWasCalled(a => a.StoryListing = testList);
but i expected that the mock object would hold state and i could check the property directly. Am i doing something wrong or is this just the way you have to use rhino mocks ie: the mock object cant hold state as when i do the assert.areequal nunit says the mockView.List property is null.

By default, mocks don't handle get/set properties (not sure why. There's a way to change it but I can't remember offhand). You can generate your mockView as a stub (MockRepository.GenerateStub<IDefault>()) -- and stubs support property behavior.

Related

Facing issue when trying to fake helper function

I am using Nunit and FakeItEasy for my MVC Controller functions.
My Test Code:
[Test]
public async Task Search_Success()
{
if (!isFakeInitialized)
InitializeFake();
url = "/N/UserSvc/v1/Types?skip=0&take=" + Constants.MaxSearchRowNumber;
Types= A.CollectionOfFake<Type>(3);
List<Type> found=new List<Type>(Types);
A.CallTo(() => nFake.GetDataAsync<IEnumerable<Type>>(fakeHttpSession, url)).Returns(Types);
var fakeHelper = A.Fake<helperFunctions>();
A.CallTo(() => FakeHelper.GetAvailableTypes(fakeHttpSession, found, true)).Returns(foundTypes);
//Act
var actionResult = await myController.SearchView();
var viewResult = actionResult as ViewResult;
//Assert
Assert.IsNotNull(viewResult);
Assert.AreEqual("Search", viewResult.ViewName);
}
I am getting error at
A.CallTo(() => nFakeHelper.GetAvailableTypes(fakeHttpSession, found, true)).Returns(foundTypes);
Error: cannot convert lambda expression to type object because it is not a delegate type.
Here is the helper function Code:
public List GetAvailableTypes(Session session,List allTypes,bool includeAllType)
{
List results = new List();
return results;
}
How can i overcome the error.
If nothing else, your A.CallTo should fail because GetAvailableLicenseTypes isn't virtual. I'm a little surprised at the error message, though.
I've tried to reproduce, but had to trim things down quite a bit and fill in missing code, and ended up getting
The current proxy generator can not intercept the specified method for the following reason:
- Non virtual methods can not be intercepted.
Are you able to include more information, starting with the full error, including stack trace?
var nmsFakeHelper = A.Fake<NMCHelperFunctions>();
A.CallTo(() => nmsFakeHelper.GetAvailableLicenseTypes(fakeHttpSession, foundLicense, true)).Returns(foundLicensTypes);
These two lines are your issue.
The first line declares nmsFakeHelper as a fake of concrete type NMCHelperFunctions.
The second line then defines the behaviour of the fake when it's GetAvailableLicenseTypes method is called.
In the background, FakeItEasy decides what type of fake it should use (mock, stub, etc.). If the type you are asking a fake of is concrete you get a stub. However, if you want to be able to define behaviour (define return values or validate that methods were called etc.) you need a mock instead of a stub.
To get FakeItEasy to decide to return a mock instead of a stub, you need to give it an interface type instead. This is because a mock needs to be able to intercept the method calls but in .NET, methods can only be intercepted if they are virtual calls. This happens when the type you are using is an interface, but cannot happen when the type you are using is a concrete type.
So to get around this problem, you should add an interface to the NMCHelperFunctions type that includes (at the very least) the GetAvailableLicenseTypes method (as well as any other methods you may).
This means that your first line will change to the following (assuming you name your interface iNMCHelperFunctions):
var nmsFakeHelper = A.Fake<iNMCHelperFunctions>();
Your second line would remain unchanged, and your test code should now work.
You may have to refactor your application code to use the interface type instead of the concrete type. There is some benefit from doing this because it allows your components to be swappable so it's easier to add or change behaviour in the future by writing a new class that adheres to the same interface and switching to that.

How to test a service method that returns a model?

So I have a service method that modifies a model object
public function doSomething() {
$model = new Model();
// Modify the model with a bunch of private methods
return $model;
}
If I want to test doSomething, I really only have $model to work with. And the only way I can write assertions on $model is to use its public interfaces.
$this->assertEquals($model->getName(), 'name');
What confuses me here is what exactly am I testing with that assertion? Am I testing that getName works properly or am I testing doSomething works properly?
In order for me to test doSomething, I have to assume that getName works. So how do I make sure that is the case?
Based on your code, I would test that I got an instance of Model returned. And then using the public accessors or assertAttributeEquals to check that the properties of the object were correct. This does test the getters of the model, however the object having certain properties is what you are expecting to happen.
Though as your class is both creating the object and modifying it. I would change the method to take a Model as an argument. This way in my test I can create a mockModel and make sure that any public setters are called with the proper arguments. Doing this, I don't have to worry about any of the logic that Model has for properties that get set.
For Example:
Test Function:
public function testDoSomething() {
$mockModel = $this->getMock('Model');
$mockModel->expects($this->once())
->method('foo')
->with('some argument');
$mockModel->expects($this->once())
->method('bar')
->with('some other argument');
$sut = new SUT();
$sut->doSomething($mockModel);
}
Your function doSomething only needs to become this:
public function doSomething(Model $model) {
/** Do stuff with private methods **/
}
Now you are able to make sure that properties of Model are set with the proper values and not depending on the logic that may or may not exist in the class. You are also helping to specify the contract that Model needs to fill. Any new methods that you are depending on will come out in your integration / system tests.
Your contract with doSomething() is, that it has to return an object of type "Model". Your contract is not getName() working on a returned object. As result, test $model to be of correct type:
$this->assertInstanceOf('Model', $model);
Documentation: PHPUnit -> assertInstanceOf()
As a hint, "[i]deally, each test case is independent from the others" 2014-10-21 wikipedia.org/wiki/Unit_testing.
So, in your test_doSomethingTest*(), you are supposed to test only what happens within that function. Check for return type, and whatever happens withing that function. Testing getName() should be in it's own test_getName*().

Ninject Factory - "new" object being passed in instead of one called in factory method

I am using the Ninject Factory Extensions so that I can create objects that have services injected plus custom values
so:
public interface IGameOperationsFactory
{
ISpinEvaluator Create(GameArtifact game);
IReelSpinner CreateSpinner(GameArtifact game);
}
Then in module:
Bind<IGameOperationsFactory>().ToFactory().InSingletonScope();
Bind<ISpinEvaluator>().To<DefaultSpinEvaluatorImpl>();
Bind<IReelSpinner>().To<DefaultReelSpinnerImpl>();
The actual factory gets injected in a classes' constructor and is then used like:
_spinner = _factory.CreateSpinner(_artifact);
_spinEval = _factory.Create(_artifact);
Where _artifact is of type GameArtifact
Then in each of the implementation's constructors services plus the passed in objects are injected. The GameArtifact is successfully passed in the first constructor, and in the second one a "new" GameArtifact is passed in, i.e. not a null one but one with just default values as if the framework just called
new GameArtifact()
instead of passing in the already existing one!
The Constructor for the two objects is very similar, but the one that doesn't work looks like:
[Inject]
public DefaultReelSpinnerImpl(GameArtifact ga, IGameOperationsFactory factory, IRandomService serv)
{
_rand = serv;
_ra = ga.Reels;
_mainReels = factory.Create(_ra);
_winLine = ga.Config.WinLine;
}
Where the factory and serv are injected by Ninject and ga is SUPPOSED to be passed in via the factory.
Anyone have a clue why a new "fresh" object is passed in rather than the one I passed in??
I have rewritten you sample a little bit, and it seems to work fine. Could you provide more detailed code sample?
My implementation
I have changed verb Create to Get to match Ninject conventions
public interface IGameOperationsFactory
{
ISpinEvaluator GetSpinEvaluator(GameArtifact gameArtifact);
IReelSpinner GetReelSpinner(GameArtifact gameArtifact);
}
Ninject configuration
I have added named bindings to configure factory
Bind<ISpinEvaluator>()
.To<DefaultSpinEvaluatorImpl>()
.Named("SpinEvaluator");
Bind<IReelSpinner>()
.To<DefaultReelSpinnerImpl>()
.Named("ReelSpinner");
Bind<IGameOperationsFactory>()
.ToFactory();
ps: full sample with tests

WCF REST service won't return children of Entities

I have written a WCF service with the REST template that has the defaultOutgoingResponseFormat set to Json. Under that, I have built a simple entity model using Entity Framework and ObjectContext, in order to pass around custom POCO entities.
If I pass a single entity, the system works as expected. If I add children to the entity, the REST response is blank. In the debugger, the entity is populated correctly, but the service itself returns nothing at all.
So, for instance, I have a Trip.Get() method. The WCF code looks like this:
[WebGet(UriTemplate = "{id}", ResponseFormat = WebMessageFormat.Json)]
public Model.Trip Get(string id)
{
Model.Trip fetchedTrip = null;
try
{
fetchedTrip = Library.Trip.Get(new Guid(id));
}
catch (Exception ex)
{
Debug.Write(ex.Message);
}
return fetchedTrip;
}
Library.Trip.Get looks like this in the working version:
public static Model.Trip Get(Guid tripId)
{
using (Model.POCOTripContext context = new Model.POCOTripContext())
{
var tripEntity = context.Trips.FirstOrDefault(c => c.Id == tripId) ?? new Model.Trip();
return tripEntity;
}
}
This returns the expected result, which looks like this:
{"ArrivalDate":"/Date(1334203200000-0400)/","DepartureDate":"/Date(1334721600000-0400)/","Id":"d6413d96-fe1f-4b1c-ae7a-3bbf516cdc2f","Name":"Test 123","Photos":null,"PlacesOfInterest":null,"WhereTo":"Orlando, FL"}
If I change the Library method to add in the children, however, the REST service returns a blank value. Nothing, nada.
public static Model.Trip Get(Guid tripId)
{
using (Model.POCOTripContext context = new Model.POCOTripContext())
{
var tripEntity = context.Trips.Include("PlacesOfInterest").Include("Photos").Include("PlacesOfInterest.PoiAttributes").FirstOrDefault(c => c.Id == tripId) ?? new Model.Trip();
return tripEntity;
}
}
The debugger, in the WCF service on the return statement, shows that the entity is fully and correctly populated.
I am certain that I am just missing some magic attribute, and am hoping that someone who has dome this before might be able to help me out!
According to your small test with removing back tracking navigation property you have problem with serialization to JSON. Default serialization is not able to track object references so when it starts serializing your Trip it follows navigation property to points of interest and in first of them it finds reference to Trip. Because it doesn't track references it follows the navigation property and serializes trip again (and again follows his navigation properties) => infinite loop.
You must either remove your back tracking navigation property as you did in test or you must tell serializer either to track references or to exclude that property from serialization (well I'm not sure what the first option will do in case of JSON). I guess you are using default WCF serialization so either:
Mark each entity with [DateContract(IsReference = true)] and each serialized property with [DataMember] attributes to start tracking references.
Or mark back tracking navigation property with [IgnoreDataMember] attribute to exclude the property from serialization

Mocking private fields with RhinoMocks

I have the following class definition whereby the attribute field is hydrated via reflection by NHibernate. The field is not exposed as an object but instead I want to hide it's implementation and just provide properties that reference the properties of the attribute field.
public class CustomerAttribute : ICustomerAttribute
{
private IAttribute attribute;
public string DisplayName
{
get { return attribute.DisplayName;}
}
}
I'm trying to mock this object with RhinoMocks but I'm not sure how to hydrate the attribute field for testing. I've tried setting the attribute field manually via reflection but I get a proxy error from RhinoMocks (which makes sense).
So how do I hydrate the attribute field to I can test the properties of the CustomerAttribute object?
Here is my test right now...
[Test]
public void PropertiesTest()
{
MockRepository mock = new MockRepository();
ICustomerAttribute attribute = mock.StrictMock<ICustomerAttribute>();
//Set the attribute field
FieldInfo fieldInfo = typeof(CustomerAttribute).GetField("attribute",
BindingFlags.Instance | BindingFlags.SetField |
BindingFlags.NonPublic);
fieldInfo.SetValue(attribute, new Domain.Attribute()); //This does not work
Expect.Call(attribute.DisplayName).Return("Postal Code");
mock.ReplayAll();
Assert.AreEqual(true, attribute.DisplayName);
mock.VerifyAll();
}
If CustomerAttribute is your subject under test (SUT) and IAttribute is a dependency that needs to be mocked for testing, IAttribute more than likely needs to be injectable into CustomerAttribute. This should be done either via constructor (usually preferred) or property injection. Look into "Inversion of Control" if you're not familiar with it already.
Also, ICustomerAttribute should NOT be created as a mock--the concrete type should be created explicitly (i.e. "new CustomerAttribute"). After all, CustomerAttribute (the implentation!) is the what you are trying to test.
I am not sure what you are trying to test here. If you want to test your CustomerAttribute class than you need to create an instance of it (instead of mocking ICustomerAttribute).
In order to set the attribute on your CustomerAttribute you could either
Use dependency injection to inject the correct attribute and use it during testing
Use reflection of the real CustomerAttribute instance you created for testing