Other parts in this series Part 2 Part 3

While I was at the ALT.NET and MVP summits, the one topic that came up over and over again was the fact that we don’t focus on the beginners enough. And not necessarily beginners in the sense of brand new developers, but beginners in terms of those who just haven’t been exposed to many of the concepts that we work with so often. Many of us have forgotten how hard it was to grasp some of these concepts. Since Moq 3 went final while I was out of town, I felt like doing an introduction to mocking using Moq 3 was the perfect place to start!

At this point many developers are now doing automated testing, but not necessarily unit testing. The reason I say this is that most developers don’t know how to break their applications down so that the pieces can be tested independently. Mocking is an easy way to replace dependencies during testing so that you don’t need to actually call out to a database, web service, file system, or even just another class. The idea is that you are isolating small pieces of functionality during testing, hence why they call it “unit” testing.

In order to do this you must design your classes to use virtual methods or implement interfaces. To look at a simple example let’s start off with an Order class.

public class Order { public int OrderId { get; set; } public decimal OrderTotal { get; set; } }

Very simple, so that we don’t bury the concept under tons of business logic. The first thing that we are going to do is write the order out to a file, but I want to test this functionality without having to actually write my files somewhere to a disk. To do this I am first going to create an OrderWriter class:

public class OrderWriter { private readonly IFileWriter fileWriter; public OrderWriter(IFileWriter fileWriter) { this.fileWriter = fileWriter; } public void WriteOrder(Order order) { fileWriter.WriteLine(String.Format("{0},{1}", order.OrderId, order.OrderTotal)); } }

As you can see, this class takes an IFileWriter interface in its constructor and then when “WriteOrder” is called, it formats the string and passes it to the fileWriter field. The IFileWriter interface is very simple and looks like this:

public interface IFileWriter { void WriteLine(string line); }

By using this interface we have isolated the actual writing of the file to the disk from the formatting of the data that is going to be written to the disk. The tests that we wrote to form our above classes (you are using TDD, aren’t you? 🙂 look like this:

public class When_an_order_is_to_be_written_to_disk : ContextSpecification { private Order order; private Mock<IFileWriter> mockFileWriter; private OrderWriter orderWriter; public override void EstablishContext() { order = new Order(); order.OrderId = 1001; order.OrderTotal = 10.53M; mockFileWriter = new Mock<IFileWriter>(); orderWriter = new OrderWriter(mockFileWriter.Object); } public override void Because() { orderWriter.WriteOrder(order); } [Fact] public void it_should_pass_data_to_file_writer() { mockFileWriter.Verify(fw => fw.WriteLine("1001,10.53"), Times.Exactly(1)); } }

In this test I am using xUnit, which uses the “Fact” attribute to label something a test. It doesn’t use a “TestFixture” attribute or anything. And it uses the class constructor for setup instead of a method with a “Setup” attribute. Personally I really like many of the design decisions that the xUnit guys took.

Lame Disclaimer You may also notice that these tests were written in the Context/Specification manner, which I am taking a risk by using. Not because the style is risky, but because I’ll probably have 800 people ripping apart the way that I did it. Honestly though, if you have any suggestions on how these could be written in a better way, please let me know. For these tests, I tried to stick to vanilla xUnit in order to keep the new concepts as few as possible.

While these tests may look very different to you, one of the advantages of this style of test comes in when you run them:

See how you can tell what is going on? When you have multiple tests in each context, it looks even better. The more I talk to people who write tests in this style, the more I am sold on it. But anyways, this post isn’t about unit testing styles, so let’s move on!

If you go back and look at the test earlier in this post you can see that we are creating a new Order in the setup:

public override void EstablishContext() { order = new Order(); order.OrderId = 1001; order.OrderTotal = 10.53M; mockFileWriter = new Mock<IFileWriter>(); orderWriter = new OrderWriter(mockFileWriter.Object); }

Here we are setting up the context of the tests. We create a new order, set some values, then declare a mock IFileWriter and then pass it into the OrderWriter class. So we are going to test if we can write the file to disk, but we don’t want to hit the disk. So what is the point? Right? Well, not really, when writing an order to disk in a real application there could be significant logic in how to format the file. The code to actually write the file to disk should be separately tested to make sure it works, but being able to isolate the formatting of the data for the order and test it, is very useful.

We do this by creating a new “Mock” class and pass it the interface as a generic type parameter that we want to mock. Next we create the “OrderWriter” class and pass in the mocked instance of our IFileWriter interface by accessing the Object property on the Mock<IFileWriter> object. We can’t pass the Mock<IFileWriter> instance to the OrderWriter constructor because it takes an IFileWriter, and this is why the “Object” property is available. Hate to repeat myself, but the process is this:

Create an instance of Moq’s “Mock” class that takes a interface or class with virtual methods as a generic parameter. Tell the Mock what you want to happen, specifying parameters, and even return values. We will get deeper into this later on. Get back the mocked interface which will behave in the way in which you told it to. Use this mocked interface in your code. Call “Verify” or “VerifyAll” on the mock to ensure that what you said would happen actually happened. This step is not always required.

Once we get the mocked interface we can create the OrderWriter class and pass the mocked interface into it. When we pass the order into it, we will format the order and the mocked interface will get called with the formatted string representing the order. Next we want to actually perform the action that we want to test:

public override void Because() { orderWriter.WriteOrder(order); }

Here we pass the order into the OrderWriter and then next we assert that the method on the IFileWriter interface was called property with the correct values:

[Fact] public void it_should_pass_data_to_file_writer() { mockFileWriter.Verify(fw => fw.WriteLine("1001,10.53"), Times.Exactly(1)); }

When we call “Verify” on our mock with a lambda we are telling it to check that the call we pass to it actually occurred. The second parameter that we pass to it (which is optional) tells the mock how many times we expected it to be called. So here we are asking the mockFileWriter object if the “WriteLine” method was called with the value “1001,10.53” exactly one time. If this occurred, then the test will pass.

In this post we have looked at creating a mock class, tell it that a particular method will be called, and then verify that it actually happened. In the future posts we are going to look at setting up return values, dealing with properties, dealing with parameters that we don’t know at compile time, events, etc… So stay tuned!