Moq is a fabulously simple yet powerful mocking framework.
Please note, MOQ version 4.20 has introduced a SponsoreLink which appears to send data to some third party. See discussions on GitHub.
For those unaware of what a mocking framework are and what they have to offer check out Wikipedia’s Mock Object post.
Here’s the fundamentals for starting to use Moq…
Let’s start with a simple interface for us to mock out
public interface IFeed { string Name { get; set; } bool Update(int firstNPosts); }
Now to mock this interface we can simply create a mock object based on the interface, as follows
IMock<IFeed> mock = new Mock<IFeed>();
obviously this is of little use unless we can set up some behaviours, i.e. what happens when a property or method etc. is called. So in the case of this interface we might want to return a known string for Name like this
IMock<IFeed> mock = new Mock<IFeed>(); mock.Setup(f => f.Name).Returns("SomeUniqueName"); // now use the mock in a unit test IFeed feed = mock.Object; Assert.Equal("SomeUniqueName", feed.Name);
The code mock.Object gets the actual interface from the mock, i.e. in this case an IFeed.
For methods we do much the same thing
IMock<IFeed> mock = new Mock<IFeed>(); mock.Setup(f => f.Update(10)).Returns(true); // now use the mock in a unit test IFeed feed = mock.Object; Assert.True(feed.Update(10));
The examples above are a little contrived, after all we obviously are not really going to test that the mock we setup, but instead want to test something that uses the mock.
For example, what about if we have a FeedViewModel which takes an IFeed for display via WPF, something like the following
public class FeedViewModel : PropertyChangedBase { private IFeed feed; private bool showProgress; private string error; public FeedViewModel(IFeed feed) { this.feed = feed; } public string Name { get { return feed.Name; } } public void Update() { ShowProgress = true; bool updated = feed.Update(10); if(updated) { Error = "Failed to update"; } ShowProgress = false; } public bool ShowProgress { get { return showProgress; } set { this.RaiseAndSetIfChanged(ref showProgress, value); } } public string Error { get { return error; } set { this.RaiseAndSetIfChanged(ref error, value); } } }
Now we can test our FeedViewModel by creating a mock of the IFeed and passing into the FeedViewModel, allowing us to set up mock calls and check our expectations in tests.
The previous examples showed how we can use mocks to setup return values or just take the place of methods when they are called. We may, however, also wish to verify that our code did correctly call our mock objects one or more times – we can do this by marking the set up as Verifiable and then Verify the mocks at the end of the unit test, as per the following
Mock<IFeed> mock = new Mock<IFeed>(); mock.Setup(f => f.Posts).Returns(posts).Verifiable(); FeedViewModel model = new FeedViewModel(mock.Object); Assert.Equal(posts.Count, model.PostCount); mock.Verify();
In this example posts is a list of Post objects. Our view model has a property PostCount which uses the list of posts. We want to verify that the Posts property on our (new extended IFeed) was actually called. So we mark it as Verifiable() and at the end of the test we use mock.Verify(); to verify it was actually called.
We can be a little more explicit with our verifications, for example if we expect a method to be called twice, we can verify this as follows
Mock<IFeed> mock = new Mock<IFeed>(); mock.Setup(f => f.Update()).Returns(true); FeedViewModel model = new FeedViewModel(mock.Object); // do something on the model which will call the feed Update method mock.Verify(f => f.Update(), Times.Exactly(2));
So this will fail verification (with a MockException) if the Update() method is not called exactly 2 times.
We also may wish to raise events on the mocked object to see what happens in our object under test, for example assume we have a StatusChanged event on our IFeed which the FeedViewModel should subscribe to and change an Updating property upon the relevant event arguments
Mock<IFeed> mock = new Mock<IFeed>(); FeedViewModel model = new FeedViewModel(mock.Object); mock.Raise(f => f.StatusChanged += null, new StatusChangedEventArgs(StatusChange.UpdateStarted)); Assert.True(model.Updating); mock.Raise(f => f.StatusChanged += null, new StatusChangedEventArgs(StatusChange.UpdateEnded)); Assert.False(model.Updating);
In this code we’re raising StatusChanged events on the IFeed mock and expecting to see the view model’s Updating property change.