Posted on 3/13/2009 8:03:00 AM by Justin Etheredge
In the previous part of this series, we looked at how you can verify on an interface exactly what was called using Moq’s “Verify” syntax. In this entry we are going to take a look at setting up mocks with return values.
Setting Up Return Values
If you have ever done mocking before in the past then you probably know that the “classic” way of using mocks is to setup the mock before you call it. So in the last post when we had this line:
mockFileWriter.Verify(fw => fw.WriteLine("1001,10.53"), Times.Exactly(1));
which verifies, after the fact, what was called. In the “classic” way of doing things we could have written the test like this: (In Moq 2 the method was called “Expect” not “Setup”)
[Fact]
public void it_should_pass_data_to_file_writer2()
{
var order = new Order();
order.OrderId = 1001;
order.OrderTotal = 10.53M;
var mockFileWriter = new Mock<IFileWriter>();
mockFileWriter.Setup(fw => fw.WriteLine("1001,10.53")).AtMostOnce();
var orderWriter = new OrderWriter(mockFileWriter.Object);
orderWriter.WriteOrder(order);
mockFileWriter.VerifyAll();
}
Here you can see that right after we declare the mock we call “Setup” and pass the expectation to it. We then call “AtMostOnce” to make sure that it is only called a single time. After that we actually perform our test actions. At this point though we haven’t asserted anything, so we have to call “VerifyAll” on the mock that was created. This causes all setup calls to be verified, and an exception will be raised if one of the expectations weren’t met.
So the “Verify” syntax seems so much better, we don’t need to do two calls, or remember to call “VerifyAll” after the fact. So why is the original Setup syntax still there? Well, besides backward compatibility. Part of the reason is that there is one key thing that you can’t do after the fact, and that is setting up return values on method calls. Let’s start this by creating an OrderReader class which uses an IFileReader interface. The IFileReader interface has a line called “ReadLine” which returns a string.
Since we want to mock this IFileReader and call this method on it that returns a value, we need some way to setup the return value. Thanksfully, Moq provides us with an extremely easy way to do this:
public override void EstablishContext()
{
var mockFileReader = new Mock<IFileReader>();
mockFileReader.Setup(fr => fr.ReadLine()).Returns("1002,10.34");
orderReader = new OrderReader(mockFileReader.Object);
}
public override void Because()
{
order = orderReader.ReadOrder();
}
Moq can see the return type of the method that you are passing in, and then lets you return back an instance of that type. In fact, if a method is returning another interface that you need to mock, then you can return a mock type! This let’s you build up more complex interfaces from mocks.
Now that we have setup the mock and created our order, we simply call the “ReadOrder” method and we get back an order object. All that is left to assert now is that the line from the IFileReader was parsed and turned back into an order correctly:
[Fact]
public void it_should_have_order_id_set()
{
Assert.Equal(1002, order.OrderId);
}
[Fact]
public void it_should_have_order_total_set()
{
Assert.Equal(10.34M, order.OrderTotal);
}
And that was easy. But I mentioned earlier that we are able to setup two mocks and have one mock returned from the other mock. How does that work?
Returning Mocks From Other Mocks
Well, it works just like you are passing a mock to any other method. So if we have two interfaces like this:
internal interface IDoSomething
{
IDoSomethingElse GetSomethingElse();
}
internal interface IDoSomethingElse
{
string GetSomeValue();
}
Then it is as simple as doing this:
var mockSomethingElse = new Mock<IDoSomethingElse>();
mockSomethingElse.Setup(mse => mse.GetSomeValue()).Returns("Something");
var mockSomething = new Mock<IDoSomething>();
mockSomething.Setup(ms => ms.GetSomethingElse()).Returns(mockSomethingElse.Object);
And there you have it, we have created the IDoSomethingElse mock and setup expectations on its return value. Then we mock IDoSomething and when we setup its method, we simply pass the mock.Object into the “Returns” method.
Summary
In this post we have looked at setting up return values on mocks so that we can return canned values from them to satisfy the needs of calling classes. If you are setting up return values on mocks and not really verifying anything that was called on the mock, then technically you are not mocking, but instead stubbing. I guess that is a topic for another day though. I hope you enjoyed this entry, and stay tuned for the next post when we will look at mocking multiple interfaces and callbacks.