Can Rhino Mock deeper/nested members directly? - unit-testing

Is it possible to mock a stub/mock's object member call without having to define that as a stub, and also set the return value as all seperate verbose lines?
Example:
[TestMethod]
public void AssignedPermissions_AssociateExists_ReturnsEdit_Rhino()
{
//Arrange
var fakeConfiguration = MockRepository.GenerateStub<IDomainControllerConfiguration>();
var fakeAssociateRepository = MockRepository.GenerateStub<IAssociateRepository>();
fakeConfiguration.Stub(x => x.AssociateRepository).Return(fakeAssociateRepository);
fakeAssociateRepository.Stub(x=>x.GetAssociatesByRole(null,false,null)).IgnoreArguments()
.Return(new IAssociate[]{MockRepository.GenerateStub<IAssociate>()});
var domain = new DomainController(fakeConfiguration);
const AssignedPermission expected = AssignedPermission.Edit;
//Act
AssignedPermission actual = domain.AssignedPermissions();
//Assert
Assert.AreEqual(expected, actual);
}
Are all those temporary variables necessary just to stub out nested method calls?

I've never used the functionality, so I'm not 100% certain that this will work, but theoretically Rhino mocks supports "recursive mocking", which should allow you to at least cut out the fakeAssociateRepository by doing something like this:
var fakeConfiguration = MockRepository.GenerateStub<IDomainControllerConfiguration>();
fakeConfiguration.Stub(x => x.AssociateRepository.GetAssociatesByRole(null,false,null))
.IgnoreArguments()
.Return(new IAssociate[]{MockRepository.GenerateStub<IAssociate>()});
var domain = new DomainController(fakeConfiguration);
(note: code not tested, or even compiled)

Just wanted to share my input on this, since I just spent the last few hours wrestling with it. The answer posted above by Alconja absolutely works, but if you plan to use it for "AssertWasCalled" type of assertion, it does not assert the way I expected it to. It seems that the AssertWasCalled methods tried to assert the "get accessor" associated with the "nested" object.
For instance, if you wanted to do this:
fakeconfiguration.AssertWasCalled(x => x.AssociateRepository.GetAssociatesByRole(null, false, null));
You would get an exception such as
System.InvalidOperationException : Previous method 'IDomainControllerConfiguration.get_AssociateRepository();' requires a return value or an exception to throw.
Because the AssertWasCalled is asserting the get-accessor of the AssociateRepository property, rather than the GetAssociatesByRole() method. In the end, for my case I had to use the OP's methodology of creating mutliple stubs.

Related

Moq out parameters

I'm fairly new to using Moq and Nunit for unit testing and I'm having issues with one scenario. What I want is for my mock to have an out parameters which my system under test will then use to decide what action to take.
My system under test is an MVC API controller and in particular I'm trying to test the POST method. I want to return an error message for the object when validation fails.
Here is the method code for the controller:
public IHttpActionResult Post(Candidate candidate)
{
try
{
if(candidate==null)
return BadRequest();
IEnumerable<string> errors;
_candidateManager.InsertCandidate(candidate, out errors);
if (errors!=null && errors.Any())
return BadRequest(CreateErrorMessage("Invalid candidate: ", errors));
return CreatedAtRoute("DefaultApi", new {id = candidate.CandidateId}, candidate);
}
catch (Exception)
{
return InternalServerError();
}
}
This is my Unit Test Code:
[Test]
[Category("CandidateManagerController Unit Tests")]
public void Should_Return_Bad_Request_When_Creating_Invalid_Candidate()
{
IEnumerable<string> errors = new List<string>() {"error1", "error2"};
var mockManager = new Mock<ICandidateManager>();
mockManager.Setup(x => x.InsertCandidate(new Candidate(), out errors)).Callback(()=>GetErrors(errors));
var sut = new CandidateManagerController(mockManager.Object);
var actionResult = sut.Post(new Candidate());
Assert.IsInstanceOf<BadRequestResult>(actionResult);
}
What I expect is that when _candidateManager.InsertCandidate() is run then the errors variable is populated. However what is happening is that when you step through the controller code errors is null after _candidateManager.InsertCandidate() method is run.
If anyone has any ideas what I'm doing wrong or if what I want to do is not possible using Moq then please let me know.
Thanks
What you want to do is possible. If you look at the Quickstart docs at https://github.com/Moq/moq4/wiki/Quickstart, there is a section where it shows how you do setups for methods using out params. I have made two corrections to your code and it works.
You have to use the same candidate instance for both the mock setup and when you exercise the sut. Otherwise, Moq thinks that the two objects are different and your test setup becomes useless.
You don't have to use Callback in order to set the errors returned by the mocked CandidateManager.
Below is your test method with my changes.
[Test]
[Category("CandidateManagerController Unit Tests")]
public void Should_Return_Bad_Request_When_Creating_Invalid_Candidate()
{
IEnumerable<string> errors = new List<string>() {"error1", "error2"};
//instance to be used for both setup and test later
var candidate = new Candidate();
var mockManager = new Mock<ICandidateManager>();
//removed Callback
mockManager.Setup(x => x.InsertCandidate(candidate, out errors));
var sut = new CandidateManagerController(mockManager.Object);
var actionResult = sut.Post(candidate);
Assert.IsInstanceOf<BadRequestResult>(actionResult);
}
You have to make sure that when you call your SUT that you use the same instance passed to the out argument otherwise the call will fail.
In your example, the method under test passes a null instance into the mocked method thus negating the setup of the test.
If however you are not able to supply the same instances for the out then it doesn't look like you will be able to get a mock to pass successfully. Take a look a the Quick Start for Moq to get an understanding of it capabilities.

Mocking DBSet, EF Model First

As said in the title, I follow Model First method. So my Model classes are Automatically generated. If I want mock the DBContext derived MyModelContainer which contain DBSets of entity classes. Read some where that in order to unit test, you need to change it to IDBSet. Whether its possible to do it especially in a class that gets auto generated when I do "Run Custom Tool" is one concern. But as of now I modified it.
But the real problem is: when I try to Stub MyModelContainer to return a mock generated from IDBSet. Rhino mock is firing an InvalidOperationException: "Invalid call, the last call has been used, or no call has been made(make sure that you are calling a virtual(C#)/Overridable(VB) method."
Here is my unit test code.
MyModelContainer dbMock = MockRepository.GenerateMock<MyModelContainer>();
IDBSet<Models.MyEntity> entityMock = MockRepository.GenerateMock<IDBSet<Models.MyEntity>>()
dbMock.Stub( x=>x.MyEntities ).Return( entityMock );
The last statement is triggering the exception. I tried using the fake implementation of IDBSet<> specified here, But no luck!
I use MVC 4, Rhino Mocks 3.6. Any help will be appreciated.
Update:
After some trials and research, I found a fix. I changed the code to:
MyModelContainer dbMock = MockRepository.GenerateMock<MyModelContainer>();
IDBSet<Models.MyEntity> entityMock = MockRepository.GenerateMock<IDBSet<Models.MyEntity>>()
//dbMock.Stub( x=>x.MyEntities ).Return( entityMock );
dbMock.MyEntities = entityMock;
Now the InvalidOperationException is gone.
The test fails only due to ExpectationViolationException which should be normal.
As for auto generated Model class, it is found out that editing the DbContext's T4 template (.tt extension) will do the trick. Thanks to Alan's Blog
But I want to know why the previous code didn't work. Anyone?
2 reasons are possible here:
MyEntites property of MyModelContainer is not virtual.
In that case Rhino Mock can't stub this property at all. Then dbMock.Stub(x=>x.MyEntities) will fail.
MyEntites property is virtual, but has both public getter and public setter.
Then notation dbMock.Stub(x=>x.MyEntities).Return(entityMock) is not allowed. You can see explanation e.g. here.
In both cases the right fix is exactly what you did: use dbMock.MyEntities = entityMock instead of dbMock.Stub(x=>x.MyEntities).Return(entityMock).
Here is an extension method for Substituting IDbSet (with NSubstitute) to return an IQueryable
public static DbSet<T> FakeDbSet<T>(this IQueryable<T> queryable) where T : class
{
DbSet<T> fakeDbSet = Substitute.For<DbSet<T>, IQueryable<T>>();
((IQueryable<T>)fakeDbSet).Provider.Returns(queryable.Provider);
((IQueryable<T>)fakeDbSet).Expression.Returns(queryable.Expression);
((IQueryable<T>)fakeDbSet).ElementType.Returns(queryable.ElementType);
((IQueryable<T>)fakeDbSet).GetEnumerator().Returns(queryable.GetEnumerator());
fakeDbSet.AsNoTracking().Returns(fakeDbSet);
return fakeDbSet;
}
Then you can now stub the DbContext like this:
var db = NSubstitute.Substitute.For<DataContext>();
var fakeResult = emptyCustomers.FakeDbSet();
db.Customers.Returns(fakeResult);
Here is an extension method for Stubing (with RhinoMocks) IDbSet to return an IQueryable
public static class RhinoExtensions
{
public static IDbSet<T> MockToDbSet<T>(this IQueryable<T> queryable) where T : class
{
IDbSet<T> mockDbSet = MockRepository.GenerateMock<IDbSet<T>>();
mockDbSet.Stub(m => m.Provider).Return(queryable.Provider);
mockDbSet.Stub(m => m.Expression).Return(queryable.Expression);
mockDbSet.Stub(m => m.ElementType).Return(queryable.ElementType);
mockDbSet.Stub(m => m.GetEnumerator()).Return(queryable.GetEnumerator());
return mockDbSet;
}
}
Then you can now stub the DbContext like this:
_db.Stub(p => p.Customers).Return(fakeCustomers.MockToDbSet());

Unit testing with FakeItEasy against nested Entity Framework member

We are trying to unit test code that relies on the Entity Framework 4.1. I've seen several posts that implement unit testing against POCOs, but we would like to retain the default EF plumbing, so that we can easily use the EF Caching Wrapper.
FakeItEasy seems to handle abstracting away EF okay, but I'm having problems asserting what happened. For example, I have this code in my model (where there is another Email partial class that is the autogenerated code from the EF database-first wizard):
public partial class Email
{
IMyEntities _dataContext;
public Email(IMyEntities myEntities)
{
_dataContext = myEntities;
}
public void SendEmails()
{
// ... code to send emails goes here...
_dataContext.Emails.AddObject(this);
_dataContext.SaveChanges();
}
}
Then in my unit test with FakeItEasy:
var context = A.Fake<IMyEntities>();
var email = A.Fake<Email>(context);
// ... code to configure email goes here ...
email.SendEmails();
// this fails with a FakeItEasy.ExpectationException...
A.CallTo(() => context.Email.AddObject(email)).MustHaveHappened();
How can I know from my unit test that context.Emails.AddObject actually did get called?
Thank you!
You need to set the Email-property of you context to a fake:
var context = A.Fake<IMyEntities>();
var mail = A.Fake<WhateverTypeTheEmailPropertyHas>();
A.CallTo(() => context.Email).Returns(mail);
var email = A.Fake<Email>(context);
// ... code to configure email goes here ...
email.SendEmails();
// this fails with a FakeItEasy.ExpectationException...
A.CallTo(() => mail.AddObject(email)).MustHaveHappened();
Now I guess it should work.
I found a workaround that I'm not crazy about, but it does work. Instead of calling AddObject() on the child object, you can call a deprecated method, AddTo[Collection Name](), on the data context itself. Since this is just a shallow method call, it can be easily evaluated by FakeItEasy.
My code changed to this:
public void SendEmails()
{
// ... code to send emails goes here...
_dataContext.AddToEmails(this);
_dataContext.SaveChanges();
}
Then, in my unit test:
A.CallTo(_dataContext).Where(m => m.Method.Name == "AddToEmails").MustHaveHappened();
A.CallTo(() => _dataContext.SaveChanges()).MustHaveHappened();
Of course, by doing this you have the downside of always ignoring the preferred, non-deprecated, methods whenever you want to add to a collection of the data context. Not to mention, there's a good chance I'll get tripped up later on with a need to determine execution on a child object's method...
If anyone knows a better way, please share!
Thank you,
Eric

Moq - how to mock the result of a method within a method begin tested

and thank you in advance for any and all your assistance.
I have a method that I'm trying to test.
Within this method is a call to UserMembership.Validate()
//custom override but the code isn't functional yet and is outside the scope of the test.
I want to therefore mock (using moq) the return result so that the actual test of the method can succeed.
Here is the code
public LoginResponse Login(LoginRequest request)
{
var response = new LoginResponse(request.RequestId);
// Validate client tag and access token
if (!ValidateRequest(request, response, Validate.ClientTag | Validate.AccessToken))
return response;
if (!UserMembership.ValidateUser(request.UserName, request.Password))
{
response.Acknowledge = AcknowledgeType.Failure;
response.Messages = "Invalid username and/or password.";
//response.MessageCode = -4;
return response;
}
_userName = request.UserName;
return response;
}
So, my test is for LoginResponse() but I want to 'fake' the UserMembership return value (bool) to true...
Simple enough I'm sure for you guys.
TIA, Hugh.
You could probably re-title your question to "How do you use a mocking framework with unit testing 99% of the time," because you're right on track for doing just that - a very typical usage.
You're going to want to extract an interface from your UserMembership class (right click inside the class, select "refactor" and then "extract interface."), then use Moq to create mock instances of that interface for use within your tests. Then you can use Moq to "setup" the behavior of that mock to do anything you want it to during your test. The syntax would look like this:
var userMembershipMock = new Mock<IUserMembership>();
userMembershipMock.Setup(m=> m.ValidateUser(It.Is<string>(str=> str == "myUserName"), It.Is<string>(str=> str == "myPassword"))).Returns(true);
Then you would create a new instance of your class, passing in your mock instance of IUserMembership (but since you'll make your class's constructor takes an argument of the interface type, your class won't care whether you're passing it a mock or an actual UserMembership instance
MyClass myClass = new MyClass(userMembershipMock.Object);
after which you could begin actually testing the behavior of your MyClass:
var request = new LoginRequest { UserName = "myUserName", Password = "myPassword" };
LoginResponse response = myClass.Login(request);
And then you can assert that your class's response is what you expect:
Assert.AreEqual(AcknowledgeType.Success, response.Acknowledge);
or you can verify that your mock's method (or property) was invoked as you expected:
userMembershipMock.Verify(m=> m.ValidateUser(It.Is<string>(str=> str == "myUserName"), It.Is<string>(str=> str == "myPassword")), Times.Once());
and so on.
The Moq quick start page is kind of sort of a one-page read, and can teach you 99% of everything that you need to know to use it.
The only way I can think of to mock UserMembership in this case (assuming it's not a property) is to use an IoC framework like Castle Windsor or Ninject. When you use an IoC container you would refactor your calls to UserMembership into an interface (IUserMembership) and use the container to provide an implementation:
if (Container.Resolve<IUserMembership>().ValidateUser(request.UserName, request.Password))
Then in your unit test Setup you would register the implementation of IUserMembership to be the mock object:
var mock = new Mock<IUserMembership>();
Container.Register<IUserMemberhip>().Instance(mock.Object);
You would have to also create a production implementation. If this is the standard UserMembership class, this implementation will probably do nothing other than UserMembership. Although, there are other ways to mimic this kind of duck typing.

How do I test rendered views when using T4MVC with TestHelper?

How do I test which view was rendered from a controller action if what I get is a T4MVC_ActionResult? Under normal circumstances I should be able to directly use TestHelper's methods, like in the examples:
pooController.Details().AssertViewRendered().ForView("Details")
...but, since through T4MVC I get a T4MVC_ActionResult instead of a ViewResult, the part AssertViewRendered<>().ForView("Details") fails. What alternative do I have if I want to test which view was invoked?
UPDATE:
Here's the test code:
[TestMethod]
public void Theme_Controller_Details_Action_Returns_Details_View()
{
var builder = new TestControllerBuilder();
var mockThemeRepository = new Mock<IThemeRepository>();
var themeController = builder.CreateController<Evalgrid.Website.Controllers.ThemeController>(mockThemeRepository.Object);
builder.InitializeController(themeController);
var result = themeController.Details();
result.AssertViewRendered().ForView("Details");
}
I used the debugger setting a breakpoint after the result line, and its variable type is T4MVC_ActionResult, while themeController is Evalgrid.Website.controllers.ThemeController. Note that I have used the fully qualified name of the controller.
I get this:
Expected result to be of type
ViewResult. It is actually of type
T4MVC_ActionResult.
I don't know what's going on.
Actually, T4MVC should not make a difference here. If you directly instantiate your controller and call an action method, you'll get the same thing back whether you use T4MVC or not. i.e. you won't get a T4MVC_ActionResult.
It's only when you write MVC.Foo.Details() that you'll get a T4MVC_ActionResult. That's because MVC.Foo returns an instance of a derived class which does special thing, and not directly your controller class.
Does that make sense?
Update: I'm confused, as looking at the sources for TestControllerBuilder.CreateController, it has:
public T CreateController<T>(params object[] constructorArgs) where T : Controller
{
var controller = (Controller)Activator.CreateInstance(typeof(T), constructorArgs);
InitializeController(controller);
return controller as T;
}
So it's directly instantiating the type that you pass in, which should just call your normal action.
One question about your code: does your Details action method take any parameters? If so, that would explain the problem, as you're calling it with no params, which would be a T4MVC method added in the partial class.