This is not meant as a “which is best” post or even a feature blow by blow comparison but more a “I’m using JustMock lite (known henceforth as JML) how do I do this in Moq” or vice versa.
Please note, MOQ version 4.20 has introduced a SponsoreLink which appears to send data to some third party. See discussions on GitHub.
For this post I’m using Moq 4.2.1402.2112 and JML 20014.1.1424.1
For the code samples, I’m writing xUnit tests but I’m not necessarily going to write code to use the mocks but will instead call directly on the mocks to demonstrate solely how they would work. Such tests would obviously only really ensure the mocking framework worked as expected, but hopefully the ideas of the mocks usage is conveyed in as little code as possible.
Strict behaviour
By default both Moq and JML use loose behavior meaning simply that if we do not create any Setup or Arrange code for methods/properties being mocked, then the mocking framework will default them. When using strict behavior we are basically saying if a method or property is called on the mock object and we’ve not setup any behaviors for the mock object, then the mocking framework should fail – meaning we’ll get an exception from the mocking framework.
Following is an example of using the strict behavior – removing the Setup/Arrange will cause a mocking framework exception, adding the Setup/Arrange will fulfill the strict behavior and allow the code to complete
Using Moq
Mock<IFeed> feed = new Mock<IFeed>(MockBehavior.Strict);
feed.Setup(f => f.GetTitle()).Returns("");
feed.Object.GetTitle();
Using JML
IFeed feed = Mock.Create<IFeed>(Behavior.Strict);
Mock.Arrange(() => feed.GetTitle()).Returns("");
feed.GetTitle();
Removing the MockBehavior.Strict/Behavior.Strict from the mock calls will switch to loose behaviors.
Ensuring a mocked method/property is called n times
Occasionally we want to ensure that a method/property is called a specified number of times only, for example, once, at least n times, at most n etc.
Using Moq
Mock<IFeed> feed = new Mock<IFeed>();
feed.Setup(f => f.GetTitle()).Returns("");
feed.Object.GetTitle();
feed.Verify(f => f.GetTitle(), Times.Once);
Using JML
IFeed feed = Mock.Create<IFeed>();
Mock.Arrange(() => feed.GetTitle()).Returns("").OccursOnce();
feed.GetTitle();
Mock.Assert(feed);
In both examples we could change OccursOnce()/Times.Once to OccursNever()/Times.Never or Occurs(2)/Times.Exactly(2) and so on.
Throwing exceptions
On occasion we may want to mock an exception, maybe our IFeed throws a WebException if it cannot download data from a website, we want to simulate this on our mock object -then we can use the following
Using Moq
Mock<IFeed> feed = new Mock<IFeed>();
feed.Setup(f => f.Download()).Throws<WebException>();
Assert.Throws<WebException>(() => feed.Object.Download());
feed.Verify();
Using JML
IFeed feed = Mock.Create<IFeed>();
Mock.Arrange(() => feed.Download()).Throws<WebException>();
Assert.Throws<WebException>(() => feed.Download());
Mock.Assert(feed);
Supporting multiple interfaces
Occasionally we might be mocking an interface, such as IFeed but our application will check if the IFeed object also supports IDataErrorInfo (for example) and handle the code accordingly. So, without actually changing the IFeed what we would expect is a concrete class which implements both interfaces.
Using Moq
Mock<IFeed> feed = new Mock<IFeed>();
feed.As<IDataErrorInfo>();
Assert.IsAssignableFrom(typeof(IDataErrorInfo), feed.Object);
Using JML
IFeed feed = Mock.Create<IFeed>(r => r.Implements<IDataErrorInfo>());
Assert.IsAssignableFrom(typeof(IDataErrorInfo), feed);
As you can see, we add interfaces to our mock in Moq by using the As method and in JML using the Implements method, we can change these methods together to also add further interfaces to our mock as per
Using Moq
Mock<IFeed> feed = new Mock<IFeed>();
feed.As<IDataErrorInfo>().
As<INotifyPropertyChanged>();
Assert.IsAssignableFrom(typeof(IDataErrorInfo), feed.Object);
Assert.IsAssignableFrom(typeof(INotifyPropertyChanged), feed.Object);
Using JML
IFeed feed = Mock.Create<IFeed>(r =>
r.Implements<IDataErrorInfo>().
Implements<INotifyPropertyChanged>());
Assert.IsAssignableFrom(typeof(IDataErrorInfo), feed);
Assert.IsAssignableFrom(typeof(INotifyPropertyChanged), feed);
Automocking
One of the biggest problems when unit testing using mocks is when a system under test (SUT) requires many parts to be mocked and setup, or if the code for the SUT changes often, requiring refactoring of tests to simply add/change etc. the mock objects used.
As you’ve already seen with Loose behavior we can get around the need to setup every single bit of code and thus concentrate our tests on specific areas without creating a thousand and one mock’s and setup/arrange sections of code. But in a possibly ever changing SUT it would be good if we didn’t need to continually add/remove mocks which we might not be testing against.
What would be nice is if the mocking framework could work like an IoC system and automatically inject the mocks for us – this is basically what auto mocking is about.
So if we look at the code below, assume for a moment that initially the code didn’t include IProxySettings, we write our IFeedList mock and write the code to test the RssReader, now we add a new interface IProxySettings and now we need to alter the tests to include this interface even though our current test code doesn’t need it. Ofcourse with the addition of a single interface this may seem to be a little over the top, however it can easily get a lot worse.
So here’s the code…
System under test and service code
public interface IFeedList
{
string Download();
}
public interface IProxySettings
{
}
public class RssReader
{
private IFeedList feeds;
private IProxySettings settings;
public RssReader(IProxySettings settings, IFeedList feeds)
{
this.settings = settings;
this.feeds = feeds;
}
public string Download()
{
return feeds.Download();
}
}
Now when the auto mocking container mocks the RssReader, it will automatically inject mocks for the two interfaces, then it’s up to our test code to setup or arrange expectations etc. on it.
Using Moq
Unlike the code you will see (further below) for JML, Moq doesn’t come with a auto mock container by default (JML NuGet’s package will add the Telerik.JustMock.Container by default). Instead Moq appears to have several auto mocking containers created for use with it by the community at large. I’m going to concentrate on Moq.Contrib which includes the AutoMockContainer class.
MockRepository repos = new MockRepository(MockBehavior.Loose);
AutoMockContainer container = new AutoMockContainer(repos);
RssReader rss = container.Create<RssReader>();
container.GetMock<IFeedList>().Setup(f => f.Download()).Returns("Data");
Assert.Equal("Data", rss.Download());
repos.VerifyAll();
Using JML
var container = new MockingContainer<RssReader>();
container.Arrange<IFeedList>(f => f.Download()).Returns("Data");
Assert.Equal("Data", container.Instance.Download());
container.AssertAll();
In both cases the auto mock container created our RssReader, mocking the interfaces passed to it.
That’s it for now, I’ll add further comparisons as and when I get time.