As you might know, unit testing is really important to proof your code. In other tutorials, I explained the basics of unit testing and how to test known exceptions. These are basic scenarios concerning unit testing. But what happens if the class or method you are testing needs external data, like a database of a file? Or maybe the method is depending on a different class. To solve this problem we use mocking in .NET, which means creating objects that simulate the behavior of real objects. This is exactly what we want.
Table Of Contents
What Is Mocking In .NET?
Well, just what I said: Creating objects that simulate the behavior of real objects. But what does that mean? With mocking you can take control over objects. You decide what a method can return. It’s literally faking how objects/classes work.
If the class and/or method you want to test has a dependency on another object/class you want to isolate these. You don’t want to test the dependency, but only that piece of code in your object/class.
Unit tests are for testing the code. They are not allowed to access real databases or other external sources. To avoid this with unit testing we can mock the database and let the tested code ‘think’ the database exists. If you use a repository pattern you can mock this repository and control what the fake repository returns when you try to retrieve objects from the database.
And then there is stubbing. This is like mocking in .NET but with a specific set of structures. A stub is just enough code to make the class under test work. In the example of a database with a repository pattern: A stub will have enough implemented code to make the class under test – which needs the database/repository – work. Usually, this is done with an in-memory database. A mock doesn’t need an in-memory database. If you don’t configure the mock, it will just pretend to work.
Another big advantage of mocking is that you can verify a mock or a part of it has been called in your class under test. With a stub, you can’t do that.
Preparations
Before we start, it’s best to have an application with a testable class that uses external data, like a database. I used the code from the previous tutorial and changed a few things. You can find the code here:
https://github.com/KensLearningCurve/UnitTestingAndMocking
A few things to mention:
- I use the repository pattern in the DatabaseLib class library. There is an interface, IRepository, that is being injected into MyMovies.cs.
The implementation of the IRepository does some simple CRUD with the injected DataContext. - The DataContext does nothing, it’s pure for show. But it could be a working DataContext. We need the IRepository for this tutorial.
Addressing The Problem
Let’s create a unit test for the method GetAll() in the MyMovies-class. If you followed the earlier tutorials about unit testing, the test could look like this:
public class MyMoviesTests
{
[Fact]
public void Should_GetAllMovies()
{
MyMovies myMovies = new();
List<Movie> result = myMovies.GetAll().ToList();;
Assert.Equal(???, result.Count);
}
}
A few things I did:
- I added an xUnit test project to the solution.
- In that new project, I added a new class MyMoviesTest.cs.
- In the new class, I added the code as shown above.
If you repeat these steps you will notice lines 6 and 10 giving errors. Line 6 because MyMovies class has a constructor that expects an initialized class, which is based on IRepository. I could initialize the class Repository, but that forces me to create an initialize DataContext, which needs access to a database, which we don’t want. But, for argument’s sake, let’s initialize these and use them. The code would look something like this:
public class MyMoviesTests
{
[Fact]
public void Should_GetAllMovies()
{
MyMovies myMovies = new(new Repository<Movie>(new DataContext()));
List<Movie> result = myMovies.GetAll().ToList();
Assert.Equal(???, result.Count);
}
}
Maybe this should work? Sure, it would! But how many movies are returned? And how do you access the database?
That last one is easy: Add a connection string to the DataContext. But we don’t use external data sources with unit testing, so we really shouldn’t connect it to the database. But how do we get movies then? Even if we did make a connection to the database and we know how many movies there are in the database it isn’t a valid assertion. But what if someone (or another unit test) adds another movie? Then this unit test will fail.
This is where mocking comes into play.
Setting Up Mocking In .NET
To use mocking we need to follow a few steps; we need to install a NuGet package, initialize the objects/classes to mock, and then use them.
NuGet Package MOQ
Moq is a super handy and user-friendly framework for mocking in .NET. It’s been around for a long time and used a lot. When I think of it, I don’t know any other framework I could use for mocking objects in .NET, but I am sure there are.
Moq can be installed in your unit test project as a NuGet Package. You install it with the Package Manager Console with the following command:
Install-Package Moq
But you can also use the NuGet package manager in Visual Studio, search for Moq, and install it.
Just make sure you install the package in the xUnit project, where you create and manage your unit tests.
Initializing A Mock
The next thing we want to do is initialize a mock. Meaning, we want to ‘fake’ an object. Look at the code below:
Mock<IRepository<Movie>> mockedRepository = new Mock<IRepository<Movie>>();
This initializes a new mock for the generic interface IRepository<Movie>. The variable mockedRepository now contains a lot of information about the interface, including an initialized version of the IRepository.
But… We can’t initialize interfaces, right? Right. But a mock can. It will fake the methods inside the interface as if you can use them.
Setting Up Mocking In .NET
After we initialize the mock we can set it up. Meaning we can control what the methods inside the mocked object return. In this case, I can control what the method GetAll() in the IRepository will return, thus knowing how many movies this method of the mock will return.
Remember: We want to test the method in the MyMovies.cs, not the repository. And since the repository is kind of simple (just sending data back and forth without much logic), we usually don’t unit test it either.
Take a look at the following code:
Mock<IRepository<Movie>> mockedRepository = new Mock<IRepository<Movie>>();
mockedRepository.Setup(x => x.GetAll())
.Returns(new List<Movie>()
{
new() { Id = 1 },
new() { Id = 2 },
new() { Id = 3 }
}.AsQueryable);
The first line is the line I explained earlier. After this line, I used a setup method. This method is used to set up a method of the mocked object.
In this case, the method in MyMovies which we are testing, calls the GetAll method of the repository. So I want to take control of that one and let the mock return 3 movies. In other words: The mock acts as a database.
Since the IRepository GetAll() methods return an IQuerable, I need to cast the list of movies to IQueryable with the AsQueryable.
I can now finish the unit test:
[Fact]
public void Should_GetAllMovies()
{
Mock<IRepository<Movie>> mockedRepository = new Mock<IRepository<Movie>>();
mockedRepository.Setup(x => x.GetAll())
.Returns(new List<Movie>()
{
new() { Id = 1 },
new() { Id = 2 },
new() { Id = 3 }
}.AsQueryable);
MyMovies myMovies = new(new Repository<Movie>(new DataContext()));
List<Movie> result = myMovies.GetAll().ToList();
Assert.Equal(3, result.Count);
}
If you run this test you will see it will run and pass. The method myMovies.GetAll() won’t use the database, but it will use the mock mockedRepository.
Another advantage of mocking in .NET is that the number of movies the repository GetAll() will return is always 3, since we have told it to return 3 movies.
We only test the code of the class under test, which is MyMovies in this case. Here we don’t want to test the repository, since it’s only a class that is being used by MyMovies.
Verifying A Mocked Method
We now know how to initialize and set up a mock. We can use a mocked method to return what we want instead of some unknown, external source. This results in a return value of the method we are testing. But what if that method doesn’t return anything? Like, when it’s a void?
Well, first of all, you need to remember that if the test doesn’t run into an exception, the test is a success. But in some cases, you want that little bit extra. Let us take a closer look at the Delete method in the MyMovies.cs. This is a void, thus it doesn’t return anything. It could also throw an exception when the movie is not found…Right? Nope! It can throw another exception when the id is smaller or equal to 0. The Delete calls Get(int id), which can throw that exception. It sounds strange, but it is something you need to take into consideration.
public void Delete(int id)
{
Movie? toDelete = Get(id);
if (toDelete == null)
throw new MovieNotFoundException();
movieRepository.Delete(toDelete);
}
Apart from testing exceptions, you’ll need to check if the method works completely. If we use mocking in .NET we can verify the methods from mocked classes. In the example code, you see that the Delete method in MyMovies calls for movieRepository.Delete(toDelete). We don’t have to set up this method since it doesn’t have a return value. And even if it did, we don’t use it. But we can assert if this method on the repository is called and with the correct type in the parameter.
But we do need to set up the GetAll() method of the repository. This is being used by the Get(int id) method in the MyMovies. If it doesn’t find a movie we will get an exception.
Take a look at the following test
[Fact]
public void Should_DeleteAMovie()
{
Mock<IRepository<Movie>> mockedRepository = new Mock<IRepository<Movie>>();
mockedRepository.Setup(x => x.GetAll()).Returns(new List<Movie> {
new() { Id = 1 },
}.AsQueryable);
MyMovies myMovies = new(mockedRepository.Object);
myMovies.Delete(1);
mockedRepository.Verify(x => x.Delete(It.IsAny<Movie>()), Times.Once);
}
Let’s walk it from the top:
Line 4 initializes the mock for IRepository.
Line 6 sets up the GetAll() method of the IRepository. Now, when a method from the class under test uses the GetAll() method of the repository, it will receive one movie with ID 1.
Line 10 initializes the MyMovies class and adds the mocked repository to the parameters. When we look at line 12, we see that it calls the method we want to test (Delete). Finally, line 14 verifies if the Delete method of the IRepository has run only once.
The last line is the one that can check whether a method in a mocked object is called or not. In this case, I want to check if Delete(Movie entity) is called. Since I have no idea what the contents of that movie (entity) are, I use It.IsAny<Movie>(). It tells the mocked method that it doesn’t care what is used as an object as long as it is of the type Movie. The contents don’t matter.
Times.Once is a flag that tells the Verify that this method Delete(Movie entity) can only be called once during the test. The test will fail if it is called zero or more than once.
If you have a method that loops through data, which will call a mocked method more than once, you can use Times.Exactly(int callCount).
Conclusion On Mocking In .NET
This tutorial is here to give you the basics of mocking. There are way more possibilities and tricks to use with mocking. But if I would write it all down it would create a very large tutorial.
For now, remember what mocking is and what it’s for. I hope this gives you some basic idea and you can move forward with this information. Keep an eye on my website. I might create a more advanced tutorial about mocking.




