To continue the topic of unit testing, started in the previous post, let’s review Moq, a mocking library for .NET.

While the integration tests are easier to develop, and allows to reach higher code coverage in a shorter period of time, in long term low level, granular unit tests are more valuable. They allow to control the system behavior more precisely and catch any deviation as soon as it occurs. From other side, unit tests require more work and, sometimes, application’s architecture makes such tests extremely difficult to write. The common examples of such architectures are monolithic applications or tightly coupled components.

If architecture is fully monolithic – there is no magic, tools will be able to resolve it for the developer. However, if components are coupled but can be instantiated individually, using some variant of Inversion of Control (IoC) pattern, Moq can help with testing of such components. The main idea of Moq is to allow developer to use a mock object, configured to behave in a predictable way, instead of the real object. For the code consuming the mock object, there will be no difference between the mock and the real object.

For example, an application for parsing logs may include a log reader, log analyzer and log visualizer components. If the log reader implements an ILogReader interface, the log analyzer’s constructor can accept instance of the reader as a parameter. In this case, the log reader can be mocked to provide test input into the analyzer, instead of reading files from the disk.

Typical Moq usage pattern include three steps: create a mock, setup the mock behavior, call tested code, with provided mock object. Here are these stems, using the same Log Parser example:

 [Test]
 public void Test_one_entry()
 {
     var logReader = new Mock();
     logReader.Setup(x => x.NextEntry())
         .Returns("2016-05-12 12:01pm [VRB] Initializing visual subsystem...");
 
     var logAnalyzer = new LogAnalyzer(logReader.Object);
     var entry = logAnalyzer.AnalyzeNextEntry();
 
     entry.Message.Should().Be("Initializing visual subsystem...");
 }

The same as with the FluentAssertions library, possibilities of Moq go far beyond this simple example. Moq object can be configured to input parameters

logReader.Setup(x => x.SkipEntriesAndGet(10))
           .Returns("2016-05-12 12:01pm [VRB] Initializing visual subsystem...");

Or even use placeholder like It.IsAny() when the argument is not important. Moq can handle async calls, callbacks and many other scenarios. Check it out at github.com/Moq/moq4/

blog comments powered by Disqus