I have a class like the following, that I want to unit test:
public class AddUserCommand
{
IDbContext dbContext;
public AddUserCommand(IDbContext context)
{
dbContext = context;
}
public void Execute()
{
dbContext.Users.Add(new User());
dbContext.SaveChanges();
}
}
Ultimately I need to test whether the Execute method persists the new User to the database when using a real sql database connection. But for my unit tests I obviously want to use some kind of mock object. In my tests, I can make a mock IDbContext which mimics the behaviour, and it all works. I can test that the mock context contains the new user after the Execute method has been run.
My problem is that when using the mock context, the test will pass if I do not call the SaveChanges method. This is because the mock context does not need to make an sql query to actually persist the data. It 'persists' without the call to SaveChanges because the Users collection represents the persistent store.
In order to check that SaveChanges is called, many online sources (for example: http://msdn.microsoft.com/en-us/library/ff714955.aspx and http://msdn.microsoft.com/en-gb/data/dn314431.aspx) say to add something like this to the mock context:
public class MockDbContext : IDbContext
{
boolean saved;
public void SaveChanges {
saved = true;
}
}
And then test if the saved variable is true after the Execute method is called. However, what I find lacking in this approach is that such a test will pass if the Execute method did this:
public void Execute()
{
dbContext.SaveChanges();
dbContext.Users.Add(new User());
}
Which of course would not save any changes as it is done too early. I believe that mocking frameworks like RhinoMocks allow you to test the order of method calls to the mock context, but I have also read that this is not best practice (you should test the result, not the minutae of the implementation).
The problem is that the mock context does not exactly replicate what the real DbContext will do.
So my question is: is there a standard way to mock an entity framework DbContext in such a way that any additions or deletions of objects are only committed to the mock when SaveChanges is called? Or is this not something that is generally tested for?