Intro:-
Unit testing is a form of testing in which individual components are isolated from the rest of the application so their behaviour can be thoroughly validated. ASP Dot NET Core has been designed to make it easy to create unit tests, and there is support for a wide range of unit testing frameworks
Task:-
You are going to create simple ASP-dot-NET Core - unittesting app
Software Requirements:-
Ubuntu-20.04 +jit [linux-x86_64]
.NET Core- 6.0.16
.NET SDK- 6.0.408
Sqlite- 3.31.1(Optional)
Level:-
Beginner
Prerequisite:-
Knowledge of C# and text editor/visual studio code
Step 1:-
Creating the GymApp Project:-dotnet new globaljson --sdk-version 6.0.408 --output UnitTesting/GymApp
dotnet new web --no-https --output UnitTesting/GymApp --framework net6.0
dotnet new sln -o UnitTesting
dotnet sln UnitTesting add UnitTesting/GymApp
These commands create a new project named GymApp using the web template, which contains the minimal configuration for ASP Dot NET Core applications. The project folder is contained within a solution folder also called UnitTesting.
Step 2:-
Enabling the MVC Framework:-
Add the statements to the Program.cs filebuilder.Services.AddControllersWithViews();
app.MapDefaultControllerRoute();
Now Program.cs file will be :-
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllersWithViews();
var app = builder.Build();
//app.MapGet("/", () => "Hello World!");
app.MapDefaultControllerRoute();
app.Run();
Step 3:-
Creating the Application Components
Creating the Data Model
Create a folder called Models and created a class file called Product.cs within it:-
using System.Collections.Generic;
namespace GymApp.Models {
public class Product {
public string Machine_Name { get; set; } = string.Empty;
public decimal? Machine_Price { get; set; }
public static Product[] GetProducts() {
Product Treadmil = new Product {
Machine_Name = "Treadmil", Machine_Price = 275M
};
Product Cable_crossover_machine = new Product {
Machine_Name = "Cable_crossover_machine", Machine_Price = 48.95M
};
return new Product[] { Treadmil, Cable_crossover_machine };
}
}
}
The Product class defines Machine_Name and Machine_Price properties, and there is a static method called GetProducts that returns a Products array.
Step 4:-
Creating the Controller
created a Controllers
folder and added to it a class file called HomeController.cs
using Microsoft.AspNetCore.Mvc;
using GymApp.Models;
namespace GymApp.Controllers {
public class HomeController : Controller {
public ViewResult Index() {
return View(Product.GetProducts());
}
}
}
The Index action method tells ASP Dot NET Core to render the default view and provides it with the Product objects obtained from the static Product.GetProducts method.
Step 5:-
Creating the View
To create the view for the action method, You should add a Views/Home folder (by creating a Views
folder and then adding a Home folder within it) and added a Razor View called Index.cshtml,
@using GymApp.Models
@model IEnumerable<Product>
@{ Layout = null; }
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Gym App</title>
</head>
<body>
<ul>
@foreach (Product p in Model ?? Enumerable.Empty<Product>()) {
<li>Machiine_Name: @p.Machine_Name, Machine_Price: @p.Machine_Price</li>
}
</ul>
</body>
</html>
Run :-
dotnet run
Step 6:-
Creating a Unit Test Project
The convention is to name the unit test project .Tests. Run the commands shown below in the
UnitTesting folder to create the XUnit test project named GymApp.Tests, add it to the solution file, and create a reference between
projects so the unit tests can be applied to the classes defined in the GymApp project.
dotnet new xunit -o GymApp.Tests --framework net6.0
dotnet sln add GymApp.Tests
dotnet add GymApp.Tests reference GymApp
Removing the Default Test Class
The project template adds a C# class file to the test project, which will confuse the results of later examples. Delete the
UnitTest1.cs file from the GymApp.Tests folder.
Writing and Running Unit Tests
dded a class file called ProductTests.cs to the
GymApp.Tests project and used it to define the class .(The CanChangeProductPrice method contains a deliberate error)
using GymApp.Models;
using Xunit;
namespace GymApp.Tests {
public class ProductTests {
//test1
[Fact]
public void ProductName_Change() {
// Arrange
var p = new Product { Machine_Name = "Test", Machine_Price = 100M };
// Act
p.Machine_Name = "New Name";
//Assert
Assert.Equal("New Name", p.Machine_Name);
}
/test 2
[Fact]
public void ProductPrice_Change() {
// Arrange
var p = new Product { Machine_Name = "Test", Machine_Price = 100M };
// Act
p.Machine_Price = 200M;
//Assert
Assert.Equal(200M, p.Machine_Price);
}
}
}
There are two unit tests in the ProductTests class, each of which tests a behaviour of the Product model class from the
GymApp project.
A test project can contain many classes, each of which can contain many unit tests.
Conventionally, the name of the test methods describes what the test does, and the name of the class describes what is being
tested.
Fact attribute is applied to each method to indicate that it is a test. Within the method body, a unit test follows a pattern
called arrange, act, assert (A/A/A).
Arrange refers to setting up the conditions for the test.
act refers to performing the test.
assert refers to verifying that the result was the one that was expected.
The arrange and act sections of these tests are regular C# code, but the assert section is handled by xUnit.
The Fact attribute and the Asset class are defined in the Xunit namespace, for which there must be a using statement in every test class.
The methods of the Assert class are static and are used to perform different kinds of comparison between the expected and actual results.
Each Assert method allows different types of comparison to be made and throws an exception if the result is not what was expected. The exception is used to indicate that a test has failed.
Running Tests from the Command Linedotnet test
Correcting the Unit Test
The problem with the unit test is with the arguments to the Assert.Equal method, which compares the test result to the original
Price property value rather than the value it has been changed to.Assert.Equal(200M, p.Price);
Run the tests again, and you will see they all pass
Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
[xUnit.net 00:00:05.94] GymApp.Tests.ProductTests.ProductPrice_Change [FAIL]
Failed GymApp.Tests.ProductTests.ProductPrice_Change [32 ms]
Error Message:
Assert.Equal() Failure
Expected: 100
Actual: 200
Stack Trace:
at GymApp.Tests.ProductTests.ProductPrice_Change() in /home/devnation/UnitTesting/GymApp.Tests/ProductTests.cs:line 32
Failed! - Failed: 1, Passed: 1, Skipped: 0, Total: 2, Duration: 24 ms - /home/devnation/UnitTesting/GymApp.Tests/bin/Debug/net6.0/GymApp.Tests.dll (net6.0)
Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
Passed! - Failed: 0, Passed: 2, Skipped: 0, Total: 2, Duration: 13 ms - /home/devnation/UnitTesting/GymApp.Tests/bin/Debug/net6.0/GymApp.Tests.dll (net6.0)
Conclusion:-
After performing above steps, you made a base ASP-dot-NET Core -UnitTesting basic app. Also in this tutorial you have explored about unit testing.You have learned how to create the xUnit project and how to use [Fact], A/A/Aattributes. Also, you have created two tests to test your logic in the ProductTests class.