Beginning Mocking With Moq 3 – Part 2

Writing

Other parts in this series

Part 1

Part 3

In the previous entry in this series on beginning mocking using Moq, we looked at how to create a mock and then later verify that some method was called. This is probably the most basic usage of a mocking framework, which is to simply verify a method call. One of the things that is a bit confusing when looking at a statement in a test that uses a lambda is to realize that the code you are seeing in the assertion is not actually executing. So when you see a statement like this:

mockFileWriter.Verify(fw => fw.WriteLine("1001,10.53"), Times.Exactly(1));

The lambda inside of the “Verify” method:

fw => fw.WriteLine("1001,10.53")

Is being turned into an expression tree and then analyzed by Moq, not actually being executed. Whether or not you understand what I mean by that, what you need to understand is that we are merely telling Moq what to look for, not running any code.

In order to show this a bit more clearly, what would happen if in the above code we wanted to verify that any string was passed into the “WriteLine” method, not just a particular string. Well, we simply have to call the “Verify” method like this:

mockFileWriter.Verify(fw => fw.WriteLine(It.IsAny<string>()), Times.Exactly(1));

Here you can see that we replaced the “1001,10.53” string with a method call on the static class “It”:

It.IsAny<string>())

Now it may be more obvious that this code is not being executed because it no longer looks like a simple method call. You can now see that Moq will look at this method call within the “WriteLine” method and adjust the way that it verifies this method. It will still look for exactly one call to “WriteLine” but it will accept any string passed to it, and not just the one that we had previously specified.

There are also a few other ways to verify these methods calls, such as IsRegex:

fw.WriteLine(It.IsRegex("^1001"))

Here we are matching a regex to check that the string starts with 1001. There is also one additional method called “IsInRange” which will check to see if a numerical value is within a particular range.

Verifying With Predicates

To take this a step further, we can use any predicate expression to define what we want to verify as well. For those who don’t know, a Predicate is simply a delegate that returns a boolean value. So, a variable goes in, you do some sort of check and then return a true or false. So if we wanted to check for any string that is longer than 3 characters, then we could call the “It.Is” method like this:

mockFileWriter.Verify(fw => fw.WriteLine(It.Is<string>(s => s.Length > 3)), Times.Exactly(1));

Or if we wanted to check that the string started with “1001,10.53” instead of equaling that, then we could do this:

mockFileWriter.Verify(fw => fw.WriteLine(It.Is<string>(s => s.StartsWith("1001,10.53"))), Times.Exactly(1));

There is no limit to the comparisons that we can do. We could also compare against a local variable:

string expectedValue = "1001,10.53";
mockFileWriter.Verify(fw => fw.WriteLine(It.Is<string>(s => s.StartsWith(expectedValue))), Times.Exactly(1));

This way we can keep the expected value out of the verify, making it arguably easier to read.

Property Verification

Now that you know how to verify that a method was called, what happens if we need to verify that a property was set or read? Well, it actually looks very similar to method call verification above. In order to show this, lets define a “FileName” property on the IFileWriter interface that we will set with a filename by the OrderWriter class. This is likely a poor design in a real application, but it will serve our purpose here.

So now in our OrderWriter we will do this:

public void WriteOrder(Order order)
{
    fileWriter.FileName = order.OrderId + ".txt";
    fileWriter.WriteLine(String.Format("{0},{1}", order.OrderId, order.OrderTotal));
}

Here we set the filename using the order id and then call the “WriteLine” method. So we will need another test:

[Fact]
public void it_should_set_the_file_name()
{
    mockFileWriter.VerifySet(fw => fw.FileName);
}

This test will now only pass if something is assigned to the “FileName” property. The only problem is that we could set anything to this property, it isn’t necessarily what we want. Thankfully Moq provides a way for us to check that it was set to an exact value:

mockFileWriter.VerifySet(fw => fw.FileName = "1001.txt");

Sweet. Everything works as expected. Just as with the methods, we can match against the static “It” class like this:

mockFileWriter.VerifySet(fw => fw.FileName = It.Is<string>(s => s.StartsWith("1001")));

So as you can see, properties are just as easy to work with as methods are.

Wrap Up

In this post we have taken a look at how the verification lambdas work, and how we can use Moq to verify inexact parameter values. We have also taken a look at how we can check parameters using any predicate value. Then finally we take a look at how we can verify property values as well. In future entries in this series we will take a look at returning values, events, callsbacks, etc… So stay tuned!

Loved the article? Hated it? Didn’t even read it?

We’d love to hear from you.

Reach Out

Comments (9)

  1. Hi Justin is this a typo?

    mockFileWriter.VerifySet(fw => fw.FileName = "1001.txt");

    Nice simple articles thank you.

  2. @Jake Looks like a type, but it is not. I’m assuming you are talking about the single "=". This is the new syntax for checking properties in Moq 3. In order for the lambda to work in that instance its return type must be a string, if a "==" were to be put in there then the return type would be boolean and that is not what is wanted.

    It is a bit confusing, but the syntax is clean. There is an overload that takes a second parameter to check against the value set on the property, but when using strings there is some ambiguity in the API due to other overloads that take a string as a second parameter.

  3. Thank you for the nice articles.

    I kind of understand the usefulness of mocking framework, but not completely. May be it is a stupid question. I am not sure what you are asserting in the test has any value or not.

    It is little confusing that in the test you need to know too much about the internals of the WriteOrder method.

  4. @Brian The usefulness of these tests are questionable, and I even state in the post that the design where we use a property is not a good one. And yes, it may require a bit too much knowledge of the internals of the method in this case.

    @Daniel Awesome, thanks!

  5. Justin,
    This is nice work. I’m missing something though. For a class – you can mock the return value from a method, you can mock properties. What I don’t see is how do you mock a method parameter being changed. For instance if you have a method like this:
    public ReturnStatus Foo(RecordWithData DataThing);

    You can mock what ReturnStatus gives you, but how do you manage mocking expected changes in the values of the "DataThing" parameter?

    Has this been covered and I just missed it?
    Thanks

  6. Hi Justin,

    I have a quick question. Let us that my model is a list of objects. I want to verify that one property of all those objects should be set. How can I do that using verifyset.

    Regards
    Mohit Thakral

  7. The Verify method in Moq can be simplied somewhat by creating an extension method for a Mock object, example:

    public void CalledOnce(this Mock mock, Expression<Func<T,TResult expression) {
    mock.Verify(expression, Times.Once());
    }

    Then it is possible to write:

    MockMyServiceAgent.CalledOnce(m => m.SaveMyData()); m.SaveMyData, Times.Once());

    where MockMyServiceAgent is an example of a mocked test interface / class.

Leave a comment

Leave a Reply

Your email address will not be published. Required fields are marked *

More Insights

View All