In this tutorial, you will see a range of basic code samples to help you get up and running Moq. This guide is aimed at C# and ASP.NET users. Moq is a great framework that allows you to make certain parts of your application testable. Assuming you are writing your classes against an interface
, using a mocking framework will make your life much easier when writing unit tests. In these applications, you might have code that's reliant on the HttpContext
, an email provider or a database called. When tests are run, you do not want to email your customers, instead, you will want to mock this functionality. The aim is to have reliable tests that can be run. These tests can not rely on third-party services. If you write tests that require third-party services to be up and running, your test suite will be very flakey. You will spend more time wondering why tests have broken than doing valuable work! Getting up and running with Moq is pretty simple, if you want to find out how to start, read on ππ
How To Mock Something With Moq
Let us say we have this class:
To mock this class using Moq, you would write this code:
As you can see from the code above, mocking an object is simple. Simply use Mock<>
, passing the type you want to mock. When you want to use the mocked object, you use the .Object()
method. Simples .π.
How To Add Mocked Data To A Mock / How To Use MoqΒ To Mock Properties With No Setters
You now know how to mock objects, it is probably a good idea to do something a bit more useful with these mocks. In most tests, after defining your mock, the next step is to add conditions. Most conditions will return some form of dummy data when called, e.g. if this method is called, return this data. To configure a mock to return data, you will need to use the .Setup()
and .Return()
methods, like so:
With the set-up defined, we can use it like this:
The Name
property when called will now return the string value 'jon'. This setup is really simple, however, it will give you a lot of power when your write tests. In this example, 'name' doesn't even need a setter defined. This is another example of how Moq lets you test code in different ways compared to how you could test conditions in non-mocked code allows π‘
How To Add Mocked Parameter Data To A Mock
If you can follow the code above, then hopefully you should start to see a pattern. You write your classes against an interface. In your unit tests, you spend the majority of your time testing setting up your mocks by mocking the interfaces. This is mainly done with SetUp
methods. YOu can set what data a mocked object returns using Return()
:
In the code example above, if the code calls MethodWithInputParameters
with the input set as 'jon', true will be returned. Setting up each and every property on a mocked object with conditions takes time and effort. To make your life a lot easier and quicker, when using SetUp
you can omit the condition. You can configure Moq to return data regardless of the input value. This is done with It
. In the example above, Moq is being configured to match any input condition on MethodWithInputParameters
regardless of the string value that is being passed in. This approach is a lot easier than having to faff around with exact conditions in each test. Obviously, there will be times when you want to write more accurate parameters input checks, however, in most instances, It
works nicely!
How To Write Testable Code With Moq
Imagine you have a class that deals with newsletter sign-ups. You want to test the method, however, you do not want the system to send any emails. To top it off, if you tried to call the default SendSmtp()
method, an exception would be thrown and your test would fail. In our example, the code for this scenario looks like this;
When you find yourself in these types of situations where your code can't be unit tested, mocking comes into play. In most instances to make things testable, you will need to slightly re-architect your code. Let us see how to do that! Let us rewrite the code above so that it can be unit tested. The main thing we need to do is extract the call to the SMTP method into an interface. We can then mock that interface and inject it into the class. This will allow us to mock the part that can not otherwise be tested. To solve this problem, first, we need to wrap the SMTP's functionality into an interface, like so:
We can now rewrite myClass
so that it is testable. We do this by passing in the SMTP interface into the class via the constructor, like so:
The class is now written in such a way that the part of the system that was previously untestable can now be mocked. This cane achieve this by mocking the call to ISmtpSender.SendSmtp()
and adding a mocked return value of true
to it:
We can execute a unit test against this updated code and an exception will NOT be thrown. Calling myMethod()
will not throw an exception anymore! We pass the mocked object into the class, which has been configured to return true
if anything calls the SendSmtp()
method. The test will now run to completion without failing. Allowing you to test and add alterations as needed. Nice β€οΈβπ₯
We have successfully refactored our code and made it testable by building our class against an interface. Mocking the interface to allow us to test code that was previously untestable! Mocking can become a lot more complex than this simple example, however, at its heart, this is all that you need to get started. Simply rinse and repeat! Happy Coding π€