In this article, we are going to learn about XUnit Testing in .Net Core 6.0.
What is Unit Test?
A unit test is a way of testing the smallest piece of code that can be logically isolated in a system. In most programming languages, that is a function, a method, or a property.
Why do We Need Unit Tests?
Our applications can fail in unexpected ways in response if any changes take place. Hence, automatic testing is required after making all changes for applications.
Manual testing is the slowest, least reliable, and most expensive way to test an application. But if applications aren’t designed to be testable, manual testing might be the only way available to us.
so design our application in such a way that it can be testable.
To achieve this we have to follow good architectural principles like Dependency Inversion, Single Responsibility, Don’t Repeat Yourself (DRY).
Prerequisites
Let us understand with the help of an example.
First, open Visual Studio 2022 and create a .NET 6.0 application by clicking Create a new project.
Choose ASP.NET Core Web API.
Now, set the Project Name and Location, and then click on the Next button.
Now, set the Target Framework as .NET 6.0, and then click on the Create button.
Now create a User Class in the Model folder and paste the below code in it.
using System.ComponentModel.DataAnnotations; namespace WebApiDemo.Model { public class User { public Guid Id { get; set; } [Required] public string? UserName { get; set; } public int Age { get; set; } public string? Email { get; set; } } }
Now create UserController in the controller folder and paste the below code in it.
using Microsoft.AspNetCore.Mvc; using WebApiDemo.Model; using WebApiDemo.Services; namespace WebApiDemo.Controllers { [Route("api/[controller]")] [ApiController] public class UserController : ControllerBase { private readonly IUserService _service; public UserController(IUserService service) { _service = service; } // GET api/Users [HttpGet] public ActionResult<IEnumerable<User>> Get() { var items = _service.GetAllUser(); return Ok(items); } // GET api/Users/5 [HttpGet("{id}")] public ActionResult<User> Get(Guid id) { var item = _service.GetUserById(id); if (item == null) { return NotFound(); } return Ok(item); } // POST api/Users [HttpPost] public ActionResult Post([FromBody] User value) { if (!ModelState.IsValid) { return BadRequest(ModelState); } var item = _service.AddUser(value); return CreatedAtAction("Get", new { id = item.Id }, item); } // DELETE api/Users/5 [HttpDelete("{id}")] public ActionResult Remove(Guid id) { var existingItem = _service.GetUserById(id); if (existingItem == null) { return NotFound(); } _service.RemoveUser(id); return Ok(); } } }
Next, Create IUserService Interface in the new Services folder and paste the below code.
using WebApiDemo.Model; namespace WebApiDemo.Services { public interface IUserService { IEnumerable<User> GetAllUser(); User AddUser(User newUser); User GetUserById(Guid id); void RemoveUser(Guid id); } }
Create UserService Class in the same Services folder and paste the below code.
using WebApiDemo.Model; namespace WebApiDemo.Services { public class UserService: IUserService { private readonly List<User> _users; public UserService() { _users = new List<User>() { new User() { Id = new Guid("ab2bd817-98cd-4cf3-a80a-53ea0cd9c200"), UserName="Hafeezjaha", Age=22, Email= "hafeeza@gmail.com", }, new User() { Id = new Guid("cd5089dd-9754-4ed2-b44c-488f533243ef"), UserName="Shaikh", Age=21, Email= "Shaikh@gmail.com", }, new User() { Id = new Guid("66ff5116-bcaa-4061-85b2-6f58fbb6db25"), UserName="Jaha", Age=23, Email= "Jaha@gmail.com", }, }; } public IEnumerable<User> GetAllUser() { return _users; } public User AddUser(User newUser) { newUser.Id = Guid.NewGuid(); _users.Add(newUser); return newUser; } public User GetUserById(Guid id) { var existing = _users.Where(a => a.Id == id).FirstOrDefault(); return existing; } public void RemoveUser(Guid id) { var existing = _users.First(a => a.Id == id); _users.Remove(existing); } } }
This small API project we are going to test with the help of the xUnit Test.
The below steps are used to Set up a web API testing project.
let’s right-click on New Solution in our created project.
Then Search xUnit and then choose the xUnit test project .NET core option and then click on the next button.
Now, set the Project Name and Location, and then click on the Next button.
Now, set the Target Framework as .NET 6.0, and then click on the Create button.
After creating the testing project structure look like this.
Then the first thing we need to do is to add references to our existing project.
Right-click on Dependencies –> Project References.
Then check the WebApiDemo project and then click the OK button.
When we created the unit testing project, a file was created by default. Let us modify the file name, so right-click on the UnitTest1.cs file and rename this file UserControllerTest.cs
Then open it and paste the below code in it.
using Microsoft.AspNetCore.Mvc; using System; using System.Linq; using WebApiDemo.Controllers; using WebApiDemo.Model; using WebApiDemo.Services; using Xunit; namespace ApiTestProject { public class UserControllerTest { UserController _controller; IUserService _service; public UserControllerTest() { _service = new UserService(); _controller = new UserController(_service); } [Theory] [InlineData("ab2bd817-98cd-4cf3-a80a-53ea0cd9c200", "ab2bd817-98cd-4cf3-a80a-53ea0cd9c111")] public void GetUserByIdTest(string guid1, string guid2) { //Arrange var validGuid = new Guid(guid1); var invalidGuid = new Guid(guid2); //Act var notFoundResult = _controller.Get(invalidGuid); var okResult = _controller.Get(validGuid); //Assert Assert.IsType<NotFoundResult>(notFoundResult.Result); Assert.IsType<OkObjectResult>(okResult.Result); //Now we need to check the value of the result for the ok object result. var item = okResult.Result as OkObjectResult; //We Expect to return a single user Assert.IsType<User>(item.Value); //Now, let us check the value itself. var userItem = item.Value as User; Assert.Equal(validGuid, userItem.Id); Assert.Equal("Hafeezjaha", userItem.UserName); } [Fact] public void AddUserTest() { //OK RESULT TEST START //Arrange var completeUser = new User() { UserName = "Jaha", Age = 23, Email = "Jaha@gmail.com" }; //Act var createdResponse = _controller.Post(completeUser); //Assert Assert.IsType<CreatedAtActionResult>(createdResponse); //value of the result var item = createdResponse as CreatedAtActionResult; Assert.IsType<User>(item.Value); //check value of this user var userItem = item.Value as User; Assert.Equal(completeUser.UserName, userItem.UserName); Assert.Equal(completeUser.Age, userItem.Age); Assert.Equal(completeUser.Email, userItem.Email); //OK RESULT TEST END //BADREQUEST AND MODELSTATE ERROR TEST START //Arrange var incompleteUser = new User() { UserName = "Jaha", Email = "Jaha@gmail.com" }; //Act _controller.ModelState.AddModelError("Age", "Age is a requried filed"); var badResponse = _controller.Post(incompleteUser); //Assert Assert.IsType<BadRequestObjectResult>(badResponse); //BADREQUEST AND MODELSTATE ERROR TEST END } [Theory] [InlineData("ab2bd817-98cd-4cf3-a80a-53ea0cd9c200", "ab2bd817-98cd-4cf3-a80a-53ea0cd9c111")] public void RemoveUserByIdTest(string guid1, string guid2) { //Arrange var validGuid = new Guid(guid1); var invalidGuid = new Guid(guid2); //Act var notFoundResult = _controller.Remove(invalidGuid); //Assert Assert.IsType<NotFoundResult>(notFoundResult); Assert.Equal(3, _service.GetAllUser().Count()); //Act var okResult = _controller.Remove(validGuid); //Assert Assert.IsType<OkResult>(okResult); Assert.Equal(2, _service.GetAllUser().Count()); } } }
Arrange: this means that we need to arrange or set up the necessary parameters for the test.
Act: means just do the action which might be calling a method, calling a controller.
Assert: means just evaluating the result.
That’s it run your all test case.
Here you can see our all test cases run successfully.
That’s it.
Also check, File Upload Using FTP In .Net Core 6.0