Using Moq to Mock void methods

2,880 views
Skip to first unread message

Andy Collins

unread,
Feb 3, 2011, 1:07:19 PM2/3/11
to Moq Discussions
I'm trying to work out how this Mock (using the Moq framework) stuff
all works, but I've become a bit confused with methods that return
void.

The original object has the following methods/properties:

void Add(Person entity);
void Save();
IQueryable<Person> Persons;


The Add method calls InsertOnSubmit (it's Linq to sql), and the Save
method calls Context.SubmitChanges(). The Person's property returns
the Table<News> object.

I'm not sure how I go about mocking these methods however, as I
obviously can't use Returns().

Or does my design mean that I can't actually Mock the objects properly?

David Allen

unread,
Feb 3, 2011, 5:26:27 PM2/3/11
to moq...@googlegroups.com
Mocking aids testing. How or which thing to mock depends on which part of code is the code under test and which classes are the dependencies. Understanding dependency injection helps. As you implied, not all designs are easily testable.
 
Can you express a test case in the following form?
Given <initial condition>
When <action>
Then <expected result>
This will help me understand what you are trying to test.
And I also need to understand which class is the code under test and which class is the dependency. I am also unclear which class contains the InsertOnSubmit method.
 
Let's say you have a
public class Foo{
public void Save(IContext context){ context.SubmitChanges();} 
...}
 
And you wish to do the following test
Given a Foo, which depends on an IContext object
When we call foo.Save()
Then we expect that the contextObject.SubmitChanges is called.
 
Then your code under test is Foo.Save(IContext context). and your dependency is IContext. You can mock your IContext object and do two very cool things: 1) make sure that it pretends to act in certain ways, 2) verify that it has been used in certain ways.
 
Notice, however, this mocking business has some challenges. Your context object must be an interface or abstract class to be mocked by MOQ. There are tools that can mock concrete objects. But MOQ is not one of them.
 
So regarding those methods like Save() that return void. What you will want to do is mock the objects on which they depend, and test that those objects were used as expected. If the class you are testing is both the class under test and contains also the method you are verififying, there is a way to use MOQ to do that. In other words, to call the REAL implementation of Add(), and verify that another method in that same class is called when Add is called.  This post illustrates what I am talking about http://stackoverflow.com/questions/2462602/moq-how-to-mock-a-function-call-on-a-concrete-object
 
There were a lot of ideas there. This stuff is cool. So don't get discouraged. Give us a real test case and we can help you see how to do it. But we first need to know what your are testing.
regards,
David Kreth Allen
 
 



--
David Kreth Allen
http://codecontracts.info

David Allen

unread,
Feb 3, 2011, 5:30:03 PM2/3/11
to moq...@googlegroups.com
Minor correction: I should have said "Your context object must be an interface or abstract class, or have the methods to be mocked marked as Virtual" in order to be mocked by MOQ
Sorry for the sloppiness.
David Kreth Allen

 

Jeffrey Cameron

unread,
Feb 3, 2011, 5:50:05 PM2/3/11
to moq...@googlegroups.com
Hi Andy,

Which class is the System Under Test (SUT) here: a) the repository itself (I'm guessing Repository pattern from your method names) or b) something else that uses a repository (like a service in the domain-driven design (DDD) sense )?

If a) then you are trying to ensure that your Repository will actually save objects into the database.  You don't want to use mocks in this situation.  In this circumstance you want to use all real objects to ensure that everything works properly.

If b) Assuming you are using Repository Pattern then the purpose of Repository Pattern is to abstract things like Linq2Sql from your unit tests.  You shouldn't care how a particular object comes back to you, only that the Repository takes care of the implementation and you don't need to worry about it. Let's say you are testing a service (in the DDD sense) that uses a Repository to get objects to work on.  In this circumstance you don't care about Linq2Sql at all, it should be transparent from your service.  In this case you would not want to mock the Save method at all (because it shouldn't matter to the service).  You might want to mock the Persons property though in this case you might do something like this:

var people = new List<Person>();
// fill people up with real or mock people objects here
var mock = new Mock<IRepository>();
mock.Setup(x => x.Persons).Returns(() => people); // <-- note the lambda expression here.  When you are returning IEnumerable<T> or IQueryable<T> use a lambda expression here otherwise if you try to call Persons twice then you will get all of your people the first time, and nothing the second time.

In general, and there are differing schools of thought out there, when you use mocks you generally want to mock anything that is not the SUT.  If you're trying to figure out if your service work in a unit test, then you make a real service and mock anything used by the service.

HTH

Reply all
Reply to author
Forward
0 new messages