We are going to discuss unit tests using xUnit and Moq here step-by-step in detail, I suggest you read my following blog for a basic understanding of unit test case
Unit Test using xUnit in .NET Core 6 with the help of VS Code
Introduction
- Unit Testing is a software design pattern that is used to test the smallest components in the software development phase.
- Unit Testing is used to validate the functionality which is to create expected output before going to the production environment and QA Team.
- It helps to detect issues at the early phase of the software development cycle
- There are many unit test tools that are already present while using .NET Framework like xUnit, NUnit, and many more.
xUnit
- xUnit is a free and open-source Unit testing framework for .NET development
- xUnit has many features which provide for writing a clean and good unit test case.
- It has many attributes like Fact, Theory, and many more to write test cases effectively and cleanly and also provides a mechanism to create our own attribute
Attributes of xUnit
[Fact] attribute is used by xUnit in .NET which identifies the method for unit test
[Fact]
public void EvenNumberTest() {
//Arrange
var num = 6;
//Act
bool result = Mathematics.IsEvenNumber(num);
//Assert
Assert.True(result);
}
[Theory] attribute is used to supply parameters to the test method
[Theory]
[InlineData(5)]
public void OddNumberTest(int num) {
//Act
bool result = Mathematics.IsOddNumber(num);
//Assert
Assert.True(result);
}
Test Pattern
Arrange-Act-Assert is a great way to write clean and more readable unit test cases
Arrange
In the arrange section we setup and declare some inputs and configuration variable
Act
In the Act section, we put main things and functionality like method calls, API calls, and something like that
Assert
Assert checks expected outputs and check whether they will match our functional requirement or not
Moq
- Basically, Moq is the library that is used for mocking purposes.
- Suppose our application is dependent on one or more services at that time we don’t need to initialize all the things related to that we just use the Moq library to mock some classes and functionality with dummy data.
Step 1
Create a new .NET Core API Project

Step 2
Configure your project

Step 3
Provide additional information about your project

Step 4
Project Structure

Step 5
Install Following NuGet Packages

Step 6
Create the Models folder and create a new class Product
namespace UnitTestMoqFinal.Models
{
public class Product
{
public int ProductId { get; set; }
public string ProductName { get; set; }
public string ProductDescription { get; set; }
public int ProductPrice { get; set; }
public int ProductStock { get; set; }
}
}
Step 7
Next, Create DbContextClass inside the Data folder for data manipulation
using Microsoft.EntityFrameworkCore;
using UnitTestMoqFinal.Models;
namespace UnitTestMoqFinal.Data
{
public class DbContextClass : DbContext
{
protected readonly IConfiguration Configuration;
public DbContextClass(IConfiguration configuration)
{
Configuration = configuration;
}
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"));
}
public DbSet<Product> Products { get; set; }
}
}
Step 8
Later on, Create IProductService and ProductService class for abstraction and dependency injection inside the Services folder.
using UnitTestMoqFinal.Models;
namespace UnitTestMoqFinal.Services
{
public interface IProductService
{
public IEnumerable<Product> GetProductList();
public Product GetProductById(int id);
public Product AddProduct(Product product);
public Product UpdateProduct(Product product);
public bool DeleteProduct(int Id);
}
}
Create ProductService class
using UnitTestMoqFinal.Data;
using UnitTestMoqFinal.Models;
namespace UnitTestMoqFinal.Services
{
public class ProductService : IProductService
{
private readonly DbContextClass _dbContext;
public ProductService(DbContextClass dbContext)
{
_dbContext = dbContext;
}
public IEnumerable<Product> GetProductList()
{
return _dbContext.Products.ToList();
}
public Product GetProductById(int id)
{
return _dbContext.Products.Where(x => x.ProductId == id).FirstOrDefault();
}
public Product AddProduct(Product product)
{
var result = _dbContext.Products.Add(product);
_dbContext.SaveChanges();
return result.Entity;
}
public Product UpdateProduct(Product product)
{
var result = _dbContext.Products.Update(product);
_dbContext.SaveChanges();
return result.Entity;
}
public bool DeleteProduct(int Id)
{
var filteredData = _dbContext.Products.Where(x => x.ProductId == Id).FirstOrDefault();
var result = _dbContext.Remove(filteredData);
_dbContext.SaveChanges();
return result != null ? true : false;
}
}
}
Step 9
After that, Create a new ProductController
using Microsoft.AspNetCore.Mvc;
using UnitTestMoqFinal.Models;
using UnitTestMoqFinal.Services;
namespace UnitTestMoqFinal.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class ProductController : ControllerBase
{
private readonly IProductService productService;
public ProductController(IProductService _productService)
{
productService = _productService;
}
[HttpGet("productlist")]
public IEnumerable<Product> ProductList()
{
var productList = productService.GetProductList();
return productList;
}
[HttpGet("getproductbyid")]
public Product GetProductById(int Id)
{
return productService.GetProductById(Id);
}
[HttpPost("addproduct")]
public Product AddProduct(Product product)
{
return productService.AddProduct(product);
}
[HttpPut("updateproduct")]
public Product UpdateProduct(Product product)
{
return productService.UpdateProduct(product);
}
[HttpDelete("deleteproduct")]
public bool DeleteProduct(int Id)
{
return productService.DeleteProduct(Id);
}
}
}








nasir niazPosted May 25, 2023, 12:51 PM
Great Article. Thanks for sharing jaydeep
Aleksandar SmukovPosted Aug 29, 2022, 7:59 PM
Hi Jaydeep. Why we need to arrange in GetProductByID_Product() like this productService.Setup(x => x.AddProduct(productList[2])).Returns(productList[2])? Is it possible to arrange same as in GetProductList_ProductList() and still get productResult that is not null?