Demo
Implement Unit Testing in ASP.NET Core
Create ASP.NET Core Web API Project
For Implementation of unit testing in ASP.NET Core, I will be using Visual
Studio 2022
to create a new project of type ASP.NET Core Web API
• Launch Visual Studio 2022
• Select Create a new project
Click create You
will get
Add interface & class for Maths Service
Create IMathsService as interface
Code for it
namespace WebApplication1
{
public interface IMathsService
{
double Add(double x1, double x2); double
Subtract(double x1, double x2); double
Multiply(double x1, double x2); double
Divide(double x1, double x2);
}
}
Now we will add class for math service that will implement interface
IMathsService in Services/MathService.cs as shown below
namespace WebApplication1
{
public class MathsService : IMathsService
{
public double Add(double x1, double x2)
{
throw new NotImplementedException();
}
public double Divide(double x1, double x2)
{
throw new NotImplementedException();
}
public double Multiply(double x1, double x2)
{
throw new NotImplementedException();
}
public double Subtract(double x1, double x2)
{
throw new NotImplementedException();
}
}
}
I have not implemented the functions in Maths Service as we will write Unit
Tests first allow those test to fail before we add implementation of these
function to make the unit tests pass
Register Maths Service in Startup
We have added the Maths service so now lets register this service in the
dependency injection container so that we can inject this service into the
controller using the constructor of the controller. To register Maths service we
will add the below line of code PROGRAM.CS class
using WebApplication1;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container. builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
//Remaining code has been removed
builder.Services.AddTransient<IMathsService, MathsService>(); var
app = builder.Build();
// Configure the HTTP request pipeline. if
(app.Environment.IsDevelopment())
{
app.UseSwagger(); app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers(); app.Run();
Add a controller for Maths operations
NEED TO ADD WEB API CATEGORY EMPTY PATTERN
Let’s add Controllers\MathsController.cs to implement endpoints for Maths
operations and in this, we will inject this Math Service and use this service to
implement actions as shown below
NOW CODE FOR IT
using Microsoft.AspNetCore.Http; using
Microsoft.AspNetCore.Mvc;
namespace WebApplication1.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class MathsController : ControllerBase
{
private IMathsService _mathService = null;
public MathsController(IMathsService mathService)
{
_mathService = mathService;
}
[HttpPost] [Route("Add")]
public double Add(double x1, double x2)
{
return _mathService.Add(x1, x2);
}
[HttpPost] [Route("Divide")]
public double Divide(double x1, double x2)
{
return _mathService.Divide(x1, x2);
}
[HttpPost] [Route("Multiply")]
public double Multiply(double x1, double x2)
{
return _mathService.Multiply(x1, x2);
}
[HttpPost] [Route("Subtract")]
public double Subtract(double x1, double x2)
{
return _mathService.Subtract(x1, x2);
}
}
}
Now that our demo project is ready lets implement automated unit testing in
ASP.NET Core for service MathsService.cs.
Setup Unit Testing in ASP.NET Core
We will add a new project of the type ‘xUnit Test Project’ for .NET Core to the
solution. This project will hold the automated units tests for the MathsService
and will be used to code unit testing in ASP.NET Core
Add a new project for xUnit
• Right-click on solution file in solution explorer and select Add-
>New Project
• Select the project type as ‘xUnit Test Project’ and click on the Next
button (you can use the search option to filter the project of type
xUnit as shown below)
The test class is a blank class in which you will have to create test methods. In
xUnit.net no attribute is required at the class level to make it part of text
classes. Normally you should create one class for each unit/component being
tested. In this test class, you will have to add a test method and these methods
will be responsible for testing the condition coded in actually implemented
components.
These test method normally consists of 3 logical parts to test the conditions.
• Arrange – prepare the data which will be required for testing
i.e. data used to test scenario along with the expected result.
• Act – call the method which is being tested making use of the
data prepared in Arrange & this should return the actual result
• Assert – Compare expected result & actual result to decide if
the test passed for failed.
The unit test project will have a dependency on the project that is being tested
so you will have to add a reference to the project being tested in the unit test
project.
To demonstrate unit testing in ASP.NET Core let’s add the test class to this
project as MathServiceTest.cs and write code to test the MathsService Maths
operations as shown below.
using System;
using System.Collections.Generic; using
System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TestProject1
{
public class MathServiceTests
{
}
}
using System;
using System.Collections.Generic; using
System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TestProject1
{
public class MathServiceTests
{
private MathsService _unitUnderTesting = null; public
MathServiceTests()
{
if (_unitUnderTesting == null)
{
_unitUnderTesting = new MathsService();
}
}
[Fact]
public void Add()
{
double x1 = 5; double x2 = 8;
double expected = 13;
var actual = _unitUnderTesting.Add(x1, x2); Assert.Equal(expected, actual,
0);
}
[Fact]
public void Substract()
{
double x1 = 10; double x2 =
8; double expected = 2;
var actual = _unitUnderTesting.Subtract(x1, x2); Assert.Equal(expected,
actual, 0);
}
[Fact]
public void Multiply()
{
double x1 = 5; double x2 = 8;
double expected = 40;
var actual = _unitUnderTesting.Multiply(x1, x2); Assert.Equal(expected,
actual, 0);
}
[Fact]
public void Divide()
{
double x1 = 100; double x2 =
10; double expected = 10;
var actual = _unitUnderTesting.Divide(x1, x2); Assert.Equal(expected,
actual, 0);
}
}
}
NOW FOR THIS
WE ARE GETTING ERROR
SOLUTION
Also, as explained above you will have to add a project reference of the
project which contains MathsService class to this xUnit Test Project to be able
to test the MathService class.
HOW
Now error we go
using System.Threading.Tasks; using
WebApplication1;
namespace TestProject1
{
public class MathServiceTests
{
private MathsService _unitUnderTesting = null; public
MathServiceTests()
{
if (_unitUnderTesting == null)
{
_unitUnderTesting = new MathsService();
}
}
Code Explanation
• In the constructor, we are creating an instance of class MathsService
and making it available globally withing the test class
MathServiceTests
• We have declared four methods (Add, Subtract, Multiply & Divide)
with the attribute [Fact] that will make these method part of unit
testing and execute these methods during each test run.
• Assert.Equal is used to compare the expected result with the actual
result to verify if the test was successful or not.
Run the unit tests & let them fail
To test unit testing in ASP.NET Core let’s execute the unit test using Test
Explorer in Visual Studio. If this run all test will fail as we have still not
implemented the MathService class. Below is the screenshot of test results
from Test Explorer showing that all 4 unit tests have failed with the error
message System.NotImplementedException
It will take some time
Add Code to MathsService for Unit Tests to Pass
All the 4 unit tests failed as we have not implemented functions in
MathsService class so let’s now write the required code in MathsService class
for unit tests to pass. Add below code to MathsService.cs file
namespace WebApplication1
{
public class MathsService : IMathsService
{
//public double Add(double x1, double x2)
//{
// throw new NotImplementedException();
//}
//public double Divide(double x1, double x2)
//{
// throw new NotImplementedException();
//}
//public double Multiply(double x1, double x2)
//{
// throw new NotImplementedException();
//}
//public double Subtract(double x1, double x2)
//{
// throw new NotImplementedException();
//}
public double Add(double x1, double x2)
{
return (x1 + x2);
}
public double Divide(double x1, double x2)
{
if (x2 == 0)
{
throw new DivideByZeroException("x2 cannot be zero");
}
return (x1 / x2);
}
public double Multiply(double x1, double x2)
{
return (x1 * x2);
}
public double Subtract(double x1, double x2)
{
return (x1 - x2);
}
}
}
After adding the above code to MathsService class run all the unit tests again
from Test Explorer and this time all the tests will pass as shown below.
Now
But if we do chane in
[Fact]
public void Add()
{
double x1 = 5; double x2
= 8;
double expected = 10;
var actual = _unitUnderTesting.Add(x1, x2);
Assert.Equal(expected, actual, 0);
}
And then run