Unit Tests in .NET Core: An Introduction

Today’s header image was created by Andrew Neel, the original source for the image is available here
Now that you’ve built your first .NET Core application, it’s time to start thinking about unit tests.
What Is Unit Testing?
Unit Tests are small blocks of code that are run outside of your source code; their main purpose is to make assertions about and test the processes and algorithms used in your application’s source code.
Unit Tests are also a main component of TDD (Test Driven Development). In TDD, tests are written before any code is (which means that the test will initially fail), then the source code is built which will pass the test.
How Is Unit Testing Done In .NET Core?
Unit Tests are provided via a test library, and the test library runs against the rest of the source code.
A quick note before we begin actually building the tests: The source code used in this blog post can be found here
To show off how unit tests are created and run in .NET Core, we’re going to build an application that takes two numbers, and returns the sum of them.
It’s a pretty simple example, but it’s best to start small I guess.
Here’s the folder layout that we’re going to create:

It’s a pretty simple layout:
- All of our source code will be located within the src directory
- The application that we’re going to build will be located within the app directory
- The library that we’re going to build will be located within the library directory
- The test library code will be located within the test-library directory (which is within the test directory)
App and Library
The Application and Library code are relatively simple. Here’s a break down of the Library:
- In the Library, there is a single class called Thing.
- Within the Thing class there is a single method called Get
- Get has the following algorithm:
- Take two integers and sum them
- Store the result in a string (using String Interpolation)
- Using JSON.NET deserialise the string back to an integer
- Return the integer
And here is the code:
using static Newtonsoft.Json.JsonConvert; | |
namespace Library | |
{ | |
public class Thing | |
{ | |
// Takes two ints, adds them, stores them in | |
// a string (using string interpolation), | |
// then deserialises (via Json.Convert) back | |
// to an int and returns that value | |
public int Get(int left, int right) => | |
DeserializeObject<int>($"{left + right}"); | |
} | |
} |
Super simple, right? On to Application!
- Application creates a new instance of the Thing class
- It then calls the Get method – passing 19 and 23 to it
- The result of the Get method are then sent the the Console
And here is the code:
using static System.Console; | |
using Library; | |
namespace ConsoleApplication | |
{ | |
public class Program | |
{ | |
public static void Main(string[] args) | |
{ | |
// Basic use of the Thing class Get method | |
var thing = new Thing(); | |
WriteLine($"The answer is {thing.Get(19, 23)}"); | |
} | |
} | |
} |
Again, this is pretty simple.
Test-Library
Aside from the project.json (which I’ve ignored for App and Library, but you can read at the GitHub link) Test-Library contains a single class called LibraryTests. And here it is:
using Library; | |
using Xunit; | |
namespace TestApp | |
{ | |
public class LibraryTests | |
{ | |
// A stupid test class which assets that 19 + 23 | |
// is 42, via the Thing class' Get method | |
// Note: The Fact attribute tells the xunit | |
// that TestThing is a single test. | |
[Fact] | |
public void TestThing() | |
{ | |
Assert.Equal(42, new Thing().Get(19, 23)); | |
} | |
} | |
} |
Here’s what it does:
- TestThing creates an instance of the Thing class
- TestThing calls the Get method of the Thing class and passes it two integers – 19 and 23
- TestThing then Asserts that the returned value is equal to 42
How Do We Add a Unit Test?
And now we’re going to recreate the test-library class.
The first thing you’ll want to do is move to the test-library directory (creating it and it’s parent directory, if it doesn’t exist yet).
One you’ve done that, you need to tell .NET Core to create a new test library. So from the terminal enter the following:
dotnet new -t xunittest |
This tells .NET Core to create a new class of the type (provided by the -t switch) xunittest.
You can read more about xunit and how to write tests using it over at the xunit GitHub page
This will create a project.json file in the test-library folder, but it will be incomplete. Here’s the incomplete project.json file:
{ | |
"version": "1.0.0-*", | |
"buildOptions": { | |
"debugType": "portable" | |
}, | |
"dependencies": { | |
"System.Runtime.Serialization.Primitives": "4.1.1", | |
"xunit": "2.1.0", | |
"dotnet-test-xunit": "1.0.0-rc2-192208-24" | |
}, | |
"testRunner": "xunit", | |
"frameworks": { | |
"netcoreapp1.0": { | |
"dependencies": { | |
"Microsoft.NETCore.App": { | |
"type": "platform", | |
"version": "1.0.0" | |
} | |
}, | |
"imports": [ | |
"dotnet5.4", | |
"portable-net451+win8" | |
] | |
} | |
} | |
} |
The only problem with this project.json is that we haven’t told the test runner where to get the library classes from. To do this, we just need to add a reference to the dependencies section:
"dependencies": { | |
"System.Runtime.Serialization.Primitives": "4.1.1", | |
"xunit": "2.1.0", | |
"dotnet-test-xunit": "1.0.0-rc2-192208-24", | |
"library": { | |
"target": "project" | |
} | |
} |
This tells the test runner that we want a reference to ‘library’ and that it is a project. If we left the ‘target’ key empty, then the test runner would assume that we want a reference to a NuGet package called ‘library’, which will fail (unless there really is a NuGet package called ‘library’, but I haven’t found one).
Now that we have the project.json set up, we need to create a Tests.cs file and copy the content in from earlier in the blog post.
Here it is again, in case you don’t want to scroll back up:
Because, lets face it, developers are lazy
using Library; | |
using Xunit; | |
namespace TestApp | |
{ | |
public class LibraryTests | |
{ | |
// A stupid test class which assets that 19 + 23 | |
// is 42, via the Thing class' Get method | |
// Note: The Fact attribute tells the xunit | |
// that TestThing is a single test. | |
[Fact] | |
public void TestThing() | |
{ | |
Assert.Equal(42, new Thing().Get(19, 23)); | |
} | |
} | |
} |
Once you’ve saved Tests.cs, we can run the tests from the terminal. Assuming that you’re still in the test-library directory:
dotnet test |
This will tell the .NET Core test runner to parse the project.json from within the test-library. From here, it will restore any NuGet packages, and it will build the Library class. Once it has restored the packages and built the library class, it will build the LibraryTests class.
After all of that, .NET Core’s test runner then start the LibraryTest class and load the compiled Library. Each method with the [Fact] attribute will be run, in turn.
Here’s an example output from when I ran the tests:
Project library (.NETStandard,Version=v1.6) was previously compiled. Skipping compilation. | |
Project test-library (.NETCoreApp,Version=v1.0) was previously compiled. Skipping compilation. | |
xUnit.net .NET CLI test runner (64-bit osx.10.12-x64) | |
Discovering: test-library | |
Discovered: test-library | |
Starting: test-library | |
Finished: test-library | |
=== TEST EXECUTION SUMMARY === | |
test-library Total: 1, Errors: 0, Failed: 0, Skipped: 0, Time: 0.288s | |
SUMMARY: Total: 1 targets, Passed: 1, Failed: 0.program.cs |
You’ll notice that compilation was skipped because I’d already done a build.
And that’s it. Adding tests is easy – just remember to use the [Fact] attribute for each new test, and remember to Assert on the result.