Tuesday, March 4, 2025

NUnit Testing and Moq

 

 Initial Steps for Service Layer Testing in ASP.NET Core (NUnit + Moq)

We will set up unit testing for the Service Layer using:

  • ✅ NUnit (for testing framework)
  • ✅ Moq (for mocking dependencies)
  • ✅ FluentAssertions (for better assertions)

🔹 Step 1: Install Dependencies

Open the Package Manager Console in Visual Studio and run:

powershellt
Install-Package NUnit Install-Package Moq Install-Package FluentAssertions Install-Package Microsoft.NET.Test.Sdk Install-Package NUnit3TestAdapter

Alternatively, add dependencies in .csproj:

xml
<ItemGroup> <PackageReference Include="NUnit" Version="3.13.3" /> <PackageReference Include="Moq" Version="4.18.2" /> <PackageReference Include="FluentAssertions" Version="6.11.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" /> <PackageReference Include="NUnit3TestAdapter" Version="4.3.1" /> </ItemGroup>

🔹 Step 2: Create a Test Project

1️⃣ Right-click the solution → Add → New Project
2️⃣ Select "xUnit Test Project" or "NUnit Test Project"
3️⃣ Name it: DemoJune2024EmsSystem.Tests
4️⃣ Add reference to the main project (DemoJune2024EmsSystem):

  • Right-click Test Project → Add Reference → Select Main Project

🔹 Step 3: Create a Sample Service to Test

In the main project (DemoJune2024EmsSystem), define:

📌 IEmployeeService.cs

public interface IEmployeeService
{
    List<Employee> GetAllEmployees();
    Employee GetEmployeeById(int id);
    bool AddEmployee(Employee employee);
}

c

📌 EmployeeService.cs

public class EmployeeService : IEmployeeService
{
    private readonly IEmployeeRepository _employeeRepository;

    public EmployeeService(IEmployeeRepository employeeRepository)
    {
        _employeeRepository = employeeRepository;
    }

    public List<Employee> GetAllEmployees()
    {
        return _employeeRepository.GetAllEmployees();
    }

    public Employee GetEmployeeById(int id)
    {
        if (id <= 0)
            throw new ArgumentException("Invalid Employee ID");

        return _employeeRepository.GetEmployeeById(id);
    }

    public bool AddEmployee(Employee employee)
    {
        if (employee == null || string.IsNullOrEmpty(employee.Name))
            return false;

        _employeeRepository.AddEmployee(employee);
        return true;
    }
}



🔹 Step 4: Create the Unit Test Class

Inside DemoJune2024EmsSystem.Tests project, create:

📌 EmployeeServiceTests.cs

using DemoJune2024EmsSystem.Models;
using DemoJune2024EmsSystem.Repository;
using DemoJune2024EmsSystem.Services;
using FluentAssertions;
using Moq;
using NUnit.Framework;
using System;
using System.Collections.Generic;

namespace DemoJune2024EmsSystem.Tests
{
    [TestFixture] // Marks the class as a test class
    public class EmployeeServiceTests
    {
        private Mock<IEmployeeRepository> _employeeRepositoryMock;
        private EmployeeService _employeeService;

        [SetUp] // Runs before each test
        public void Setup()
        {
            _employeeRepositoryMock = new Mock<IEmployeeRepository>();
            _employeeService = new EmployeeService(_employeeRepositoryMock.Object);
        }

        [Test]
        public void GetAllEmployees_ShouldReturnListOfEmployees()
        {
            // Arrange
            var employees = new List<Employee>
            {
                new Employee { Id = 1, Name = "John Doe" },
                new Employee { Id = 2, Name = "Jane Doe" }
            };
            _employeeRepositoryMock.Setup(repo => repo.GetAllEmployees()).Returns(employees);

            // Act
            var result = _employeeService.GetAllEmployees();

            // Assert
            result.Should().NotBeNull().And.HaveCount(2);
            result[0].Name.Should().Be("John Doe");
        }

        [Test]
        public void GetEmployeeById_ShouldReturnEmployee_WhenIdIsValid()
        {
            // Arrange
            var employee = new Employee { Id = 1, Name = "John Doe" };
            _employeeRepositoryMock.Setup(repo => repo.GetEmployeeById(1)).Returns(employee);

            // Act
            var result = _employeeService.GetEmployeeById(1);

            // Assert
            result.Should().NotBeNull();
            result.Name.Should().Be("John Doe");
        }

        [Test]
        public void GetEmployeeById_ShouldThrowException_WhenIdIsInvalid()
        {
            // Arrange
            int invalidId = -1;

            // Act
            Action act = () => _employeeService.GetEmployeeById(invalidId);

            // Assert
            act.Should().Throw<ArgumentException>().WithMessage("Invalid Employee ID");
        }

        [Test]
        public void AddEmployee_ShouldReturnTrue_WhenValidEmployeeIsProvided()
        {
            // Arrange
            var employee = new Employee { Id = 1, Name = "John Doe" };
            _employeeRepositoryMock.Setup(repo => repo.AddEmployee(employee));

            // Act
            var result = _employeeService.AddEmployee(employee);

            // Assert
            result.Should().BeTrue();
        }

        [Test]
        public void AddEmployee_ShouldReturnFalse_WhenEmployeeIsNull()
        {
            // Act
            var result = _employeeService.AddEmployee(null);

            // Assert
            result.Should().BeFalse();
        }

        [Test]
        public void AddEmployee_ShouldReturnFalse_WhenNameIsEmpty()
        {
            // Arrange
            var employee = new Employee { Id = 1, Name = "" };

            // Act
            var result = _employeeService.AddEmployee(employee);

            // Assert
            result.Should().BeFalse();
        }
    }
}



🔹 Step 5: Run the Tests

1️⃣ Open Test Explorer in Visual Studio (Test → Test Explorer)
2️⃣ Click Run All to execute the tests
3️⃣ The tests should pass ✅


🔹 Explanation of Test Cases

Test CaseExpected Behavior
GetAllEmployees_ShouldReturnListOfEmployeesReturns a list of employees from the repository
GetEmployeeById_ShouldReturnEmployee_WhenIdIsValidFetches an employee correctly
GetEmployeeById_ShouldThrowException_WhenIdIsInvalidThrows an exception for invalid IDs
AddEmployee_ShouldReturnTrue_WhenValidEmployeeIsProvidedSuccessfully adds an employee
AddEmployee_ShouldReturnFalse_WhenEmployeeIsNullFails to add a null employee
AddEmployee_ShouldReturnFalse_WhenNameIsEmptyFails when employee name is empty

🔹 Summary

✔ Service Layer Testing is essential because it verifies business logic.
✔ Moq is used to mock the Repository Layer, so tests run independently.
✔ NUnit and FluentAssertions make tests cleaner and more readable.
✔ These tests are fast and do not require a database connection.

No comments:

Post a Comment