4

I am having trouble grasping the Moq framework. From the Moq website they give this example ...

// Assumptions:
public interface IFoo {
   public bool DoSomething(string);
   public bool TryParse(string, out string));
}

var mock = new Mock<IFoo>();
mock.Setup(foo => foo.DoSomething("ping")).Returns(true);

What is the Moq setup doing here?

// out arguments
var outString = "ack";
// TryParse will return true, and the out argument will return "ack", lazy evaluated
mock.Setup(foo => foo.TryParse("ping", out outString)).Returns(true);

Same question here .. what is being setup?

Does anyone know of a guide to Moq that maybe goes more in depth? I read this SO post where the book The Art of Unit Testing with Examples in .NET is recommended but the book is pretty old and is out of print.

Community
  • 1
  • 1
webworm
  • 9,413
  • 28
  • 96
  • 186
  • 1
    There was a [second edition](https://www.manning.com/books/the-art-of-unit-testing-second-edition) of Art of Unit Testing a couple of years ago, which is still in print AFAIK – NikolaiDante Jan 08 '16 at 18:53
  • @NikolaiDante - Wow! Didn't even check for that. Thanks! – webworm Jan 08 '16 at 18:58

1 Answers1

4

For a general background on mocking, this answer does a pretty good job explaining it and why you might want to use it in your unit tests.

Specifically, Moq is a library that allows you to easily creates mock object and control their behavior. It's easiest to describe with examples, so let's look at your first code sample:

public interface IFoo {
   public bool DoSomething(string);
   public bool TryParse(string, out string));
}

/* 1 */ var mock = new Mock<IFoo>();
/* 2 */ mock.Setup(foo => foo.DoSomething("ping")).Returns(true);

Line 1 creates a mock implementation of the IFoo interface. Under the covers, Moq is using the Castle DynamicProxy library to create a concrete implementation of IFoo on the fly, and then wrapping it in its own Mock class so we can configure its behavior.

So now that we have a mock object, we'll frequently need to configure how it responds to having its methods invoked. That way, we can test how our system under test will react to it. The Setup method on line 2 does exactly this, telling our mock object to return true when DoSomething is called with a parameter equal to "ping". Imagine you were using this mock to test a class like below:

public class TestObject 
{
    public string TestMethod(IFoo foo)
    {
        if (foo.DoSomething("ping"))
            return "ping";
        else if (foo.DoSomething("pong"))
            return "pong";
        return "blah";
    }
}

To get complete test coverage, you'd want an implementation of IFoo that can:

  1. return true for "ping" in one test
  2. return true for "pong" in another test
  3. return false for any argument in the last test

You could create your own mock object that has this behavior, e.g.:

public class MockFoo : IFoo
{
    string trueValue;

    public MockFoo(string trueValue)
    {
        this.trueValue = trueValue;
    }

    public bool DoSomething(string value)
    {
        return value == trueValue;
    }
}

But that's kind of a pain when you have complicated logic, multiple parameters, or many dependencies; it just doesn't scale well. This is where mock objects and Moq can make things easy. The same setup in Moq for the three tests is:

  1. mock.Setup(foo => foo.DoSomething("ping")).Returns(true);
    
  2. mock.Setup(foo => foo.DoSomething("pong")).Returns(true);
    
  3. mock.Setup(foo => foo.DoSomething(It.IsAny<string>())).Returns(false);
    

In my opinion, that's simpler and more expressive about how you expect your IFoo dependency to behave.

As for a guide, I think you'd be better off with a guide to mocking in general rather than a Moq-specific guide. Moq is just a library that makes using mock objects easier, and the Quickstart is a pretty good reference for the mechanics of using Moq. There are dozens of mocking tutorials and guides, just look for some. And remember, it didn't really "click" for me until I started using them. Find a coding kata and try mocking out for yourself!

Community
  • 1
  • 1
Patrick Quirk
  • 21,498
  • 1
  • 51
  • 85
  • Excellent explanation! Thank you very much for taking the time to put it all together! I will take your advice on looking for more general "mocking" tutorials. – webworm Jan 08 '16 at 19:00