Reputation: 11019
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.
Upvotes: 4
Views: 360
Reputation: 23747
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:
true
for "ping"
in one testtrue
for "pong"
in another testfalse
for any argument in the last testYou 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:
mock.Setup(foo => foo.DoSomething("ping")).Returns(true);
mock.Setup(foo => foo.DoSomething("pong")).Returns(true);
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!
Upvotes: 4