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!
Loved the article? Hated it? Didn’t even read it?
We’d love to hear from you.
Justin,
Good article. I agree that the more advanced concepts are not taught often to help beginners. In learning BDD and TDD, it has been very difficult to find good jump-off points.
Having said all of that, where is the ContextSpecification base class being defined and what is in it?
@Brian Ooops, sorry. The ContextSpecification base class is just an abstract class that has the constructor (which xUnit uses as setup. Like the [SetUp] attribute in nUnit) and two abstract methods. One called "EstablishContext" and one called "Because". Eh, I’ll just paste the code in the comment. It is probably going to come out looking like crap though.
public abstract class ContextSpecification
{
protected ContextSpecification()
{
EstablishContext();
Because();
}
public abstract void EstablishContext();
public abstract void Because();
}
Great. Thanks! Also, your "notify me when new comments are added" isn’t working. I look forward to the next part in the series…
@Brian That sucks that my "notify" thing isn’t working. I’ll look into that. Thanks for letting me know.
I am going to study moq but don’t know where to start, now i will follow your article. Thank you!
Thank you for this. It’s very enlightening. I especially find this context specification thing interesting.
– preet
Maybe this is a bad example, or maybe I just don’t get it. But either way, I fail to see the value in this test. I assume, by mocking, you are testing that the interface is being called correctly? I would also guess you will have a test for the implementation of IFileWriter that actually writes to disk, reads the results, and compares them to expected values. I see where you are going as far as using the interface.
@t_moriarty This is a very simple test, but the idea is that this test can run quickly and repeatedly because it doesn’t hit any outside resources. In a more complex application there may be a lot more to test inside of the OrderWriter.
And yes, you would want to test the IFileWriter independently to make sure that it is working correctly, but these kinds of test you would not want to run routinely on developer machines. For one reason, they can be slow, for another reason they can be hard to write without setting up directories, databases, etc… They should be run in a controlled environment like a build server.
Thank you!
The ContextSpecification class is doing a no-no, calling virtual methods from the constructor. This is actually a valid reason why xUnit made the wrong choice in eliminating the Setup method. Of course, in this case the issue may be harmless, since one would assume your derived classes would do NO initialization in the constructor, but rather would do so in EstablishContext and Because, thus removing the initialization ordering issues caused by calling virtual methods from within the constructor.
@wekempf Yep, I completely realize that it is doing this, unfortunately there is no good solution at this point. And as you said, it is unlikely to cause issues in code using this class, since it will likely be the only base class used by the test class. Although it does show a nasty error in Resharper.
I’m experimenting with a base class that could address the issue with calling a virtual from within the constructor. I’ve blogged about it here: http://wekempf.spaces.live.com/blog/cns!D18C3EC06EA971CF!689.entry. I’d be interested to hear what you think.
I may be missing something here but I’m still not sure why you need the ContextSpecification class. Can you not have just used the Constructor for initialization ??
@Sunit Sure, and that is what is happening in the base class. It provides a good template for writing your tests, making it more explicit. You certainly don’t have to use it.
As a newbie:
– Is this an ‘Arrange/Act/Assert’ pattern?
– What are the semantics about writing tests like this, and can you say a bit more about how you arrange your unit tests?
– What determines how you name your class?
– What’s the ‘Because’ all about?
– What’s the FACT attribute all about?
Thanks for a very interesting article. I enjoyed reading it.
It is the context/specification style of testing, which I was doing a simple example of. You might want to check out this post by Jimmy Bogard for a bit more inforation: http://www.lostechies.com/blogs/jimmy_bogard/archive/2008/07/24/arrange-act-assert-and-bdd-specifications.aspx
Also, the Fact attribute is from the xUnit framework. It uses "Fact" instead of "Test’. http://www.codeplex.com/xunit
Dear Justin, I have 3 words for you “You are a star”.
Please please please keep doing this work. You won so many hearts of the developers just like mine.
I want to say a big thank you for making my life easier to understand this mocking today. I really appreciate the way you started from very basic concept and moved us along.
I am not able to understand the expression
fw => fw.WriteLine(“1001,10.53”, Times.Exactly(1))
What is exactly fw means?
@Bala,
fw is the object being passed into the Action delegate.
The topic is lambda expressions.
It’s just saying that Verify, expects Action as the first parameter.
If you are unfamiliar with Action and Func, I suggest you read up on it.
Hi Justin, I really enjoyed “Beginning Mocking With Moq 3 – Part 1”. But the links to parts 2 and 3 are broken, I hope only temporarily. Thanks alot for helping me get started with Moq.
I hope that the links get fixed. Thanks again….Les
OK, If anyone else is having this problem
I found part 2 here: http://www.codethinked.com/Beginning-Mocking-With-Moq-3-Part-2
the link points here: https://www.codethinked.com/Beginning-Mocking-With-Moq-3-Part-2.aspx
I’m continueing to chug along into Moq.
Hi Justin,
Thanks for this great post. I am a newbie to developing and i have been given a task to work on writing tests for legacy code. These series of post has really helped me understanding the basics. So most of the classes in the code do not implement interfaces or are not defined as virtual. Sometimes i wonder if i turn a method to virtual, what if someone overrides it? Am i going against a good OOP design? Just a few questions that come to my mind when mocking.
Hi,
i trid your sample with UnitTesting Framework of Visual Studio 2010. And have an exception. like this: “Expected invocation on the mock exactly 1 times, but was 0 times: fw => fw.WriteLine(“1001,10.53″)
No setups configured.”
Could you please tell me, what’s wrong with the following Testcode:
//Arrange
Order order = new Order();
order.OrderId = 1001;
order.OrderTotal = 10.53M;
var mockFileWriter = new Mock();
//Act
OrderWriter orderWriter = new OrderWriter(mockFileWriter.Object);
orderWriter.WriteOrder(order);
//Assert
mockFileWriter.Verify(fw => fw.WriteLine(“1001,10.53”), Times.Exactly(1));
Hi Justin,
Very helpful tutorial. I really appreciate your posting it. One quick question. You mentioned…
“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.”
I see where we created the mock IFileWriter and verified that its WriteLine method got called correctly, but I don’t quite see where we “[told] it that a particular method [would] be called”. Isn’t that the job of the Mock.Setup method, which I don’t see used here?
Hello, I’m new to unit testing and found this series very useful, thanks. I’ve been trying to read up on the Context/Specification approach but not found much so far though. Am I right in thinking that “EstablishContext” is essentially Arrange, “Because” is Act and then the Test is assertions about what happened in the Act? If so does that mean that you end up with loads of similar classes for variations on the same scenario?
Specifically at the moment I am trying to write tests for an ASP.NET MVC Registration action. If validation succeeds they should be added to the DB and redirected, if it fails they should be redisplayed the original view. Would you have one class that Establishes the Context for a failing registration attempt and a separate class for the successful one?
@Martin You are essentially correct. The idea though is that you would end up with many tests based on the “Because”. This is only one way to write tests, and you should definitely experiment to see what works best for you.
And yes, in this method of testing you would end up with different classes for the successful and failure cases.
As I use Visual Studio on a French machine, the test failes since the fileWriter.WriteLine prints “1001,10,53” instead of “1001,10.53”. It would be better this is used instead ^^:
fileWriter.WriteLine(String.Format(“{0},{1}”, order.OrderId, order.OrderTotal.ToString(CultureInfo.InvariantCulture)));
Thank you for the awesome content, it’s always appreciated
IPTV Premium has made staying entertained so much easier. I can access all my favorite shows and movies with just a few clicks!
Your blog always leaves me feeling uplifted and inspired Thank you for consistently delivering high-quality content
I truly admire how you tackle difficult topics and address them in a respectful and thought-provoking manner
This post came at just the right time for me Your words have provided me with much-needed motivation and inspiration Thank you
I appreciate how this blog promotes self-love and self-care It’s important to prioritize our well-being and your blog reminds me of that
From the bottom of my heart, thank you for being a source of positivity and light in this sometimes dark and overwhelming world
This blog is a great resource for anyone looking to live a more mindful and intentional life Thank you for providing valuable advice and tips
I couldn’t stop scrolling and reading, your content is truly one-of-a-kind. Thank you for all the time and effort you put into creating such amazing content.
Thanks for sharing beautiful thoughts in this overwhelming world. Keep updating. Enjoyed reading