Nov 2, 2013

Moq

Moq - one of modern frameworks for mocking objects. It could do anything that could do inheritance in .NET. There is Castle under the hood, like Rhino.Mocks. But, there is no such diversity of object types - all of them are mocks. Yet there are 2 mock modes - that simplifies understanding.
And complicating thing is that Moq uses instances of Mock class to setup objects behavior and expectations. Below, Mock means Moq' class and mock means object instance that we need for test. I woud use the following style for examples:
public interface IRepository
{
    string ReadData();

    string Storage { get; set; }

    void SetData(object o);

    event EventHandler OnReading;
}

Creating objects

There are several means of creating object.
First, you could call
Mock<IRepository> mock = new Mock<IRepository>();
This constructor creates Mock for class or interface. There are several overloaded constructors - to specify mock mode, parameters for instance constructor (in case class has no parameterless constructor).
Modes available:
  • Loose - never throws, tries to return default values
  • Strict - throws in case there is no expectation for called method/property
Second option is to get mock-object directly:
IRepository repo = Mock.Of<IRepository>();
You could get an infinite collection and retrieve as many instances as you need:
IQueryable<IRepository> repos = Mocks.Of<IRepository>();
However, you would need an appropriate instance of Mock class to setup behavior of mock object:
Mock<IRepository> mock = Mock.Get(repo);

Mock abilities

You could tune mock object behavior, setup expectations.
Here are its properties:
  • Behavior - current mode, Loose or Strict
  • CallBase - should the base class be called in case expectations are not specified
  • DefaultValue - wat to return in Loose mode. You could get nulls for reference types, or try to create mocks for them automatically (you cannot create mock for sealed class obviously)
  • Object - instance of mock


Setting up behavior

There are a bunch of methods for setting up behavior:
  • Setup is used for defining expectations for methods.
  • SetupGet - for property getters
  • SetupSet - for property setters
  • SetupProperty - defines property to have "property behavior". That means that property would persist anything passed to setter.
  • SetupAllProperties - the same as SetupProperty - but for all properties at once.
All those methods allow to set expectations using Fluent method calls chain:
mock.Setup(r => r.ReadData()).Returns(() => "some result");

mock.Setup(r => r.ReadData())
     .Callback(() => Console.WriteLine("Read call"))
     .Throws<ApplicationException>();

mock.Setup(r => r.ReadData()).Verifiable();

That's quite intuitive: Returns defines what to return, Throws - what to throw, Callback - what to call.
Verifiable is for validation. All Verifiable expectations would be checked when calling Verify().

There is also SetReturnsDefault - that method sets the default value for some type. In example String    is a reference type, default value is null, but that could be changed:
mock1.SetReturnsDefault("abc");
All strings returned by mock1 by default would equal "abc".

In case arguments are not known beforehand, you could use It class:
mock.Setup(r => r.SetData(It.IsInRange("a", "c", Range.Exclusive)));
mock.Setup(r => r.SetData(It.IsAny<int>()));
mock.Setup(r => r.SetData(
    It.IsRegex("^4[0-9]{12}(?:[0-9]{3})?$")));//VISA credit card
There could be any arbitrary code:
Expression<Func<string, bool>> fridayPredicate =
    v => v == "HelloWorld" &&
    DateTime.Now.DayOfWeek == DayOfWeek.Friday;
mock.Setup(r => r.SetData(It.Is(fridayPredicate)));

Validation

There is no Fluent interface, but a lot of Verify methods, similar to Setup.
You could verify all expectations, marked as Verifiable - or just all expectation disregarding of marks (Verify and VerifyAll).
Also you could verify if particular class member has been called (with configurable error message and number of calls that is expected - from Never to range):
var mock = new Mock<IRepository>();

mock.Verify();

mock.VerifyAll();

mock.Verify(r=>r.ReadData(), "Read Data was not called");
mock.Verify(r=>r.SetData(123));

mock.VerifyGet(r => r.Storage, Times.AtLeast(4));

mock.VerifySet(r => r.Storage = "", 
    Times.Between(1, 10, Range.Exclusive));

Class It for arguments:
var mock = new Mock<IRepository>();

mock.Object.Storage = "b";

mock.VerifySet(r=>
    r.Storage = It.IsInRange("a", "c", Range.Exclusive));

Events

Events handling in Moq is quite interesting thing. There is method Raise, that accepts delegate as a first argument and EventArgs as a second. That delegate should attach a handler to event that is subject of handling. Moq runs delegate in a separate context, catching all class members calls. It catches add event method and thus knows what event to raise. Only virtual events could be handled that way (which limits this functionality greatly).
Looks like this:
string called = "one";

var mock = new Mock<IRepository>();
IRepository repo = mock.Object;
repo.OnReading += (sender1, eventArgs) => { called += "called"; };

EventHandler sampleHandler = (sender, args) =>
    { throw new NotImplementedException(); };

mock.Raise(r => r.OnReading += sampleHandler, new EventArgs());

Assert.AreEqual(called, "onecalled");

Delegate code is not important, Moq intercepts assignment and does not do anything in fact.

Conclusion

Framework is light and flexible in use, API is intuitive and easy, there is no complexities because of long library growth. Obsolete members and classes have [Obsolete] attribute, code is well documented.

Sources looks fine, there are attributes [SuppressMessage] for tuning code analysis (remove warnings about intentionally made things).

I described a part of Moq, it has much more, but I think there could be issues in complex situations, in example - there is no easy way to check order of method calls. However such tests would be quite brittle - I'm not sure of their value.

I like Moq more than Rhino.Mocks, both has their own pros and cons, but simplicity and organization won.

Rhino Mocks–what is it

Rhino Mocks, the mocking framework, appeared at 2005. It hasn’t had any changes for two years and author announced that he will not support the project anymore. Then, there was a guy who decided to continue development of Rhino Mocks. I took a look at source code – he would definitely have what to change and improve. Code is abandoned, documentation is almost absent.
Here, the last update.