How to Write Unit Tests for a .NET Core Application
Learn how to write effective unit tests for a C# .NET Core application as part of TDD, or Test-Driven Development.
Join the DZone community and get the full member experience.
Join For FreeWriting unit tests is a good software engineering practice. In this article, we will learn how to create a C# .NET Core application while adhering to the Test Driven Development (TDD) approach. In the TDD approach, before implementing a functionality, you write a unit test for it. For example, if you want to write a function to add two numbers, first you'll write a failed unit test and then implement the functionality to pass the test.
In this post, we'll create a Calculator application. To start, let's follow the folder structure as outlined below:
- CalculatorApp - Solution
- CalculatorApp.Services - Application project
- CalculatorApp.Services.Tests - Test project
You can use Visual Studio to create projects; however, in this post, I will use .NET Core commands to create my projects, add tests, and run tests. You can also use MSTest or NUnit to write unit tests, but in this example, I'll use xUnit and dotnet test to write and run my unit tests.
Let's start by opening a command shell and follow along:
Creating the Application Project
To start, you'll need to create a directory called CalculatorApp. Keep in mind that you can follow any naming convention you'd like for directories, but if you'd like to follow along with this post, I would recommend following the same directory name. So, let's create the CalculatorApp directory and navigate to it.
Inside the CalculatorApp directory, we are going to create a new solution by running the following command:
dotnet new sln
After successfully running the command, you should get the message "The Template Solution File was created successfully". Also inside the CalculatorApp directory, you will find a file named calculatorapp.sln.
Next, create a directory called CalculatorApp.Services. This directory will keep the application sources, i.e. all classes of the calculator application. Navigate to the Calculatorapp.Services directory and create a class library by running the following command:
dotnet new classlib
After successfully running this command, you should get the message "The Template Class Library was created successfully". You'll also find a file named calculatorapp.services.csproj inside the CalculatorApp.Services directory. Next, you need to add this class library project to the CalculatorApp solution. To do this, navigate back to the CalculatorApp directory, and run the command:
dotnet sln add .\calculatorapp.services\calculatorapp.services.csproj
After successfully running the command, you should get the message "Project added to the solution."
Inside the CalculatorApp.Services folder, you will find a class Class1 — rename it to Calculator and modify the class as shown in the listing below:
Calculator.csusing System;
namespace calculatorapp.services
{
public class Calculator
{
public int Add(int num1, int num2)
{
throw new NotImplementedException();
}
public int Sub(int num1, int num2)
{
throw new NotImplementedException();
}
}
}
You'll notice in the above listing that the Add and Sub functions are not implemented. First, we will write a unit test and then implement these functionalities.
Creating the Test Project
To add test projects, create a directory called CalculatorApp.Services.Tests and navigate to the directory. In this directory, we will create an MS Test project by running the following command:
dotnet new mstest
This command creates the test project which uses MS Test as the test library. Once the test project is created, add the source project library in the test project. To do that, run the command:
dotnet add reference ../CalculatorApp.Services/CalculatorApp.Services.csproj
This command will add a reference of the CalculatorAppService project to the test project. After adding the reference, add the test project to the solution by navigating to the CalculatorApp root directory, and run the command:
dotnet sln add .\CalculatorAppServices.tests\CalculatorAppServices.Tests.csproj
This command will add the test project to the solution. After successfully running the command, you should get the message "Project added to the solution."
Writing Unit Tests
So far, we've created the application source project and a test project. In the application source project, there are unimplemented functions. Now let us write tests for these functions.
In the Test project, I have renamed the file UnitTest1.cs to Calculator.Test.cs and the class name to CalculatorTest. In the constructor of CalculatorTest, we need to create an object of the Calculator class. This can be done as shown in the listing below:
Calculator.Test.csusing Microsoft.VisualStudio.TestTools.UnitTesting;
using calculatorapp.services;
namespace CalculatorApp.Services.Tests
{
[TestClass]
public class CalculatorTest
{
Calculator _calc;
public CalculatorTest()
{
_calc = new Calculator();
}
}
}
Unit Test for the Add function
In the CalculatorTest class, add a unit test method to test the Add functionality, as shown in the listing below:
[TestMethod]
public void shouldaddtwonumbers()
{
int res = _calc.Add(5, 3);
Assert.AreEqual(res, 8);
}
To run the test, navigate to the CalculatorApp.Services.Tests directory and execute the command:
dotnet test
You'll get a "test failed" output because the Add function is not implemented, as shown in the image below:
To pass the test, implement the Add function in the Calculator class as shown in the listing below:
public int Add(int num1, int num2)
{
int result = num1 + num2;
return result;
}
To run the test now, navigate to the CalculatorApp.Services.Tests director and execute the command:
dotnet test
As output, you will get the "test passed" message as shown in the image below:
Now you have implemented the Add functionality while adhering to the TDD approach in a .NET Core application!
Unit Test for the Sub function
In the CalculatorTest class, add a unit test method to test the Sub functionality, as shown in the listing below:
[TestMethod]
public void shouldsubstracttwonumbers()
{
int res = _calc.Sub(5, 3);
Assert.AreEqual(res, 2);
}
To run the test, navigate to the CalculatorApp.Services.Tests directory and execute the command:
dotnet test
Here, your test will fail because the Sub function is not implemented. You will get one failed test result, as shown in the image below:
To pass the test, implement the Sub function in the Calculator class as shown in the below listing:
public int Sub(int num1, int num2)
{
int result = num1 - num2;
return result;
}
Now run the test again by navigating to the CalculatorApp.Services.Tests directory and executing:
dotnet test
Now you'll find both tests passed, as seen here:
Now you have implemented Sub functionality while adhering to the TDD approach in a .NET Core application.
Wrapping Up
So far in this post, we've created a .NET Core Calculator application while adhering to the TDD approach. To create tests, we used the XUnit and dotnet tests. For your reference, here is the source code of both the Calculator class and its test class:
Calculator.csusing System;
namespace calculatorapp.services
{
public class Calculator
{
public int Add(int num1, int num2)
{
int result = num1 + num2;
return result;
}
public int Sub(int num1, int num2)
{
int result = num1 - num2;
return result;
}
}
}
Calculator.test.cs
using Microsoft.VisualStudio.TestTools.UnitTesting;
using calculatorapp.services;
namespace CalculatorApp.Services.Tests
{
[TestClass]
public class CalculatorTest
{
Calculator _calc;
public CalculatorTest()
{
_calc = new Calculator();
}
[TestMethod]
public void shouldaddtwonumbers()
{
int res = _calc.Add(5, 3);
Assert.AreEqual(res, 8);
}
[TestMethod]
public void shouldsubstracttwonumbers()
{
int res = _calc.Sub(5, 3);
Assert.AreEqual(res, 2);
}
}
}
And that's how you write unit tests and then implement their functionalities. I hope this post helps you in getting started with writing unit tests for your next .NET Core application!
Published at DZone with permission of Dhananjay Kumar, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments