So, in my previous post about testing MVC controller actions with Moq I left out any way to verify the calls on my MockUserRepository class. I did this because I wanted to have one MockUserRepository that I used for all tests in the UserControllerTest test class (most would refer to it as a fixture, but visual studio test likes to be different). So I factored out a class that was cleverly called “CreateMockUserRepository”. The original version of the method looks like this:
private Mock<IUserRepository> CreateMockUserRepository()
{
var user = new User()
{
Id = 10,
UserName = "TestUser",
EmailAddress = "test@test.com",
ModifiedOn = DateTime.Now,
CreatedOn = DateTime.Now
};
var mockUserRepository = new Mock<IUserRepository>();
mockUserRepository.Expect(ur => ur.GetUser(10))
.Returns(user);
mockUserRepository.Expect(ur => ur.SubmitChanges());
return mockUserRepository;
}
This all worked fine and great, and if I called “VerifyAll” on my Mock<IUserRepository> then everything would work great. But what if I wanted to reuse this method for more tests. I wanted my mock to be useful in multiple places. So, lets say I changed it to look like this:
private Mock<IUserRepository> CreateMockUserRepository()
{
var user = new User()
{
Id = 10,
UserName = "TestUser",
EmailAddress = "test@test.com",
ModifiedOn = DateTime.Now,
CreatedOn = DateTime.Now
};
var users = new List<User>()
{
new User() { Id = 10, UserName = "TestUser",
EmailAddress = test@test.com,
ModifiedOn = DateTime.Now,
CreatedOn = DateTime.Now },
new User() { Id = 11, UserName = "TestUser2",
EmailAddress = test2@test.com,
ModifiedOn = DateTime.Now,
CreatedOn = DateTime.Now }
};
var mockUserRepository = new Mock<IUserRepository>();
mockUserRepository.Expect(ur => ur.GetUser(10))
.Returns(user);
mockUserRepository.Expect(ur => ur.GetUsers())
.Returns(users);
mockUserRepository.Expect(ur => ur.SubmitChanges());
return mockUserRepository;
}
Here we have added a List<User> to hold multiple users for use with our “GetUsers” call. And at the bottom we set our expectation. So, this will now make my test for a single user edit fail. It will fail because we have setup an expectation on “GetUsers” that we never call. One solution would be to just not call “VerifyAll” knowing that my expectations aren’t going to be met, but this is obviously not ideal. Another idea would be to just create my test data and setup expectations inside of each test. I’m not a fan of this either because I have more than a few methods that need to be setup and I’d rather not have to set them up in each and every test. A third option would be for me to just create an IUserRepository stub and just use my own state variables to check that certain methods had been called. I would also rather not do this because I don’t see why I should mimic the behavior that my mocking framework already provides for me.
So what is a programmer to do?
Well, download the source and start futzing. I decided that my best course of action would be to somehow allow groups for “Verifiable” expectations. So, I figured that passing in a string was good enough for me now. I went into the Moq source and found that adding a parameter on the Verifiable and Verify methods was actually quite easy. I then copied my custom build over my old Moq dlls and I changed the last few lines in the above method to look like this:
var mockUserRepository = new Mock<IUserRepository>();
mockUserRepository.Expect(ur => ur.GetUser(10))
.Returns(user).Verifiable("SingleUser");
mockUserRepository.Expect(ur => ur.GetUsers())
.Returns(users).Verifiable("MultiUser");
mockUserRepository.Expect(ur => ur.SubmitChanges())
.Verifiable();
You’ll notice the “Verifiable” calls on the end of the “GetUser” and “GetUsers” now have string parameters where I am passing values into each of them. This add those verifications into that particular group. I could have multiple verifications in any of the groups. Then the “Verifiable” on “SubmitChanges” doesn’t have any parameters so it acts just like it always has. The idea here is that now in my single user edit, I can now make this call:
mockUserRepository.Verify("SingleUser");
And only my “GetUser” and “SubmitChanges” verifications will be tested, my “MultiUser” verification will be ignored for this test. And that is it!
So, does anyone else think that this might be a good addition to Moq? Does anyone else have a better way that I could have implemented this? (I’ve been working with Moq for all of 3 days now, so I could be missing something elementary) If so, then please let me know. Otherwise I may pull down the latest dev source and work my changes into it, then submit a patch and see if those guys might work it into a future version.
Loved the article? Hated it? Didn’t even read it?
We’d love to hear from you.
This is indeed an interesting suggestion!
Do send us the patch, and don’t forget to loop the gang at moqdisc@googlegroups.com to gather feedback on it 🙂