Mocking with NSubstitute

Monday, 16 June 2014

Unit testing is the practice of testing specific parts(units) of our code, to verify that our code works as expected. Sometimes, the code we are trying to test will have dependencies on other parts of the code that we are not trying to test. We can control these dependencies by creating mock objects.
Wikipedia says:

Mock objects are simulated objects that mimic the behavior of real objects in controlled ways

Mock objects are like fake implementations of real interfaces, that we build with custom behaviours that we define. This gives us full control of our tests as we know exactly what to expect from the mock.

NSubstitute is an easy to use mocking framework, that can be used to generate mock objects to help with unit testing. I particularly like NSubstitute because of the easy to read syntax. In the code sample below I will show how NSubstitute can be used to create mocks.

Take this bakery class:

				public class Bakery : IBakery
				{
					private readonly IDoughFactory _doughFactory;

					public Bakery()
						: this(new DoughFactory()) { }

					public Bakery(IDoughFactory doughFactory)
					{
						_doughFactory = doughFactory;
					}

					public Bread MakeBread(int typeOfDough)
					{
						var theDough = _doughFactory.GetDough(typeOfDough);

						Bread bread = Bake(theDough);

						return bread;
					}

					private Bread Bake(Dough theDough)
					{
						Bread someBread = null;

						if (theDough != null)
						{
							someBread = new Bread
							{
								Weight = theDough.Water + theDough.Flour,
								Softness = (theDough.Water/theDough.Yeast) + (theDough.Flour - theDough.Yeast)
							};
						}

						return someBread;
					}
				}
			

The bakery class has two methods, MakeBread() and Bake(). The MakeBread method first gets dough from the doughFactory, then passes that dough to the bake method, which produces bread. The Bakery class has a dependency on the doughFactory, as it needs this to produce the dough needed by the MakeBread method.

When we are writing our tests for the Bakery class we need to use a mock to simulate the behaviour of the DoughFactory. Most other mocking frameworks have concepts of Mocks, stubs and fakes, which you will need to understand in order to know which one to use. With NSubstitute, we just create a Substitute of the dependency we want to fake out, then set the behaviour if we want to.


Adding NSubstitute

Adding NSubstitute can be done through the Nuget package manager console by running this command:

			install-package nsubstitute
		

Before running the command ensure you are targeting the project you will be writing your tests in, by selecting the test project from the Default Project dropdown.

Once you have run the command, the NSubstitute library will be added to your project.


Creating a Substitute

When we want to create a new substitute we call the Substitute.For<T>() method, where T is the interface we want to create a substitute for. Here I have created a substitute for the DoughFactory and passed it into the constructor of the bakery. Now when I run my tests, they will use this substitute, instead of the actual implementation of the DoughFactory interface.

			[TestClass]
			public class BakeryTests
			{
				public IDoughFactory _doughFactory;
				public IBakery _target;

				[TestInitialize]
				public void SetupTests()
				{
					//Creates a new substitute for the IDoughFactory interface
					_doughFactory = Substitute.For<IDoughFactory>();

					_target = new Bakery(_doughFactory);
				}

				[TestMethod]
				public void MakeBread_ReturnsSomeBread()
				{
					//Arrange
						
					//Act
					var result = _target.MakeBread(1);

					//Assert
					Assert.IsNotNull(result);
				}
			}
		

Setting the Substitute Behaviour

Although I have created the substitute, my test will fail. This is because I haven't told the substitute what to do when it receives a call to the GetDough method. So by default it will return null, meaning no dough will be passed to the Bake method.

Setting the behaviour of our substitute is very simple. In the example I have created a substitute for the Dough class, and set the doughFactory to return the substitute any time the getDough method is called for any int.

				[TestClass]
				public class BakeryTests
				{
					public Dough _fakeDough;
					public IDoughFactory _doughFactory;
					public IBakery _target;

					[TestInitialize]
					public void SetupTests()
					{
						//Creates a new substitute for the IDoughFactory interface
						_doughFactory = Substitute.For<IDoughFactory>(); 

						//Creates a substitute for the dough
						_fakeDough = Substitute.For<Dough>();
						 
						_target = new Bakery(_doughFactory);
					}

					[TestMethod]
					public void MakeBread_ReturnsSomeBread()
					{
						//Arrange

						//Set the properties of the fake dough 
						_fakeDough.Flour = 12;
						_fakeDough.Water = 11;
						_fakeDough.Yeast = 3;

						//Set the behaviour for the getDough method to always return a fake dough for any integer
						_doughFactory.GetDough(Arg.Any<int>()).Returns(_fakeDough);
							
						//Act
						var result = _target.MakeBread(1);

						//Assert
						Assert.IsNotNull(result);
					}
				} 
		

Now when the test is run, it will pass.

The full source code for this example can be seen here.