Using Unit Tests in .NET Core


5 October 2018

Unit testing is a critical practice in modern software development that ensures the correctness and reliability of your application. In .NET Core, unit testing is straightforward and highly integrated into the framework, allowing you to write tests for your application logic easily. By using tools like xUnit, NUnit, and Moq, you can improve the maintainability of your application and catch potential issues early in the development process.

In this post, we’ll explore how to set up unit tests in .NET Core, using xUnit (the most common testing framework for .NET Core) and Moq for mocking dependencies.


What are Unit Tests and Why Are They Important?

Unit tests focus on testing the smallest parts of your application, often individual methods or functions, in isolation from other parts. The goal is to verify that each unit of your code behaves as expected.

Benefits of Unit Testing:

  • Catch Bugs Early: Tests can help detect issues in the codebase before they turn into bigger problems.
  • Facilitate Refactoring: With a solid suite of unit tests, you can refactor the code without the fear of breaking anything.
  • Improve Code Quality: Writing tests forces you to think about edge cases and ensure that your code handles them correctly.
  • Support for Continuous Integration: Unit tests can be integrated into CI/CD pipelines to automatically run tests after each build.

Setting Up Unit Testing in .NET Core

The first step to using unit tests in .NET Core is setting up the testing environment. .NET Core offers several testing frameworks, but we will focus on xUnit for this post. It’s simple to get started, and it’s supported natively in .NET Core.

Step 1: Create a Test Project

To add unit tests to your project, you need to create a new test project. Open a terminal or command prompt and run the following command:

dotnet new xunit -n MyProject.Tests

This command creates a new xUnit test project called MyProject.Tests. You can change the name to whatever fits your project.

Step 2: Add References to the Main Project

Next, you need to reference the main application project in your test project. You can do this by running the following command inside the test project directory:

dotnet add reference ../MyProject/MyProject.csproj

This will link your main project to the test project, allowing you to write tests that interact with the classes in your application.

Step 3: Install Moq for Mocking Dependencies

Many times, you’ll need to mock dependencies, such as services or database contexts, during unit testing. Moq is a popular library used for mocking objects in .NET Core.

To install Moq, run the following command in your test project directory:

dotnet add package Moq

Moq allows you to create mock objects that can simulate the behavior of real dependencies, ensuring that your unit tests remain isolated and focused on the component under test.


Writing Your First Unit Test

Let’s start with a simple unit test. We’ll write a test for a service method that fetches user data.

Example Service to Test

Let’s assume we have the following UserService class in our main project:

public class UserService
{
    private readonly IUserRepository _userRepository;

    public UserService(IUserRepository userRepository)
    {
        _userRepository = userRepository;
    }

    public async Task<User> GetUserByIdAsync(int userId)
    {
        return await _userRepository.GetUserByIdAsync(userId);
    }
}

The UserService depends on the IUserRepository interface to retrieve user data. The task is to write a unit test for the GetUserByIdAsync method.

Step 1: Writing the Unit Test

In your test project, create a new test class UserServiceTests.cs. Add the following code to test the GetUserByIdAsync method.

public class UserServiceTests
{
    private readonly Mock<IUserRepository> _mockUserRepository;
    private readonly UserService _userService;

    public UserServiceTests()
    {
        _mockUserRepository = new Mock<IUserRepository>();
        _userService = new UserService(_mockUserRepository.Object);
    }

    [Fact]
    public async Task GetUserByIdAsync_ShouldReturnUser_WhenUserExists()
    {
        // Arrange
        var userId = 1;
        var expectedUser = new User { Id = userId, Name = "John Doe" };

        _mockUserRepository.Setup(repo => repo.GetUserByIdAsync(userId))
            .ReturnsAsync(expectedUser);

        // Act
        var result = await _userService.GetUserByIdAsync(userId);

        // Assert
        Assert.Equal(expectedUser.Id, result.Id);
        Assert.Equal(expectedUser.Name, result.Name);
    }

    [Fact]
    public async Task GetUserByIdAsync_ShouldReturnNull_WhenUserDoesNotExist()
    {
        // Arrange
        var userId = 2;

        _mockUserRepository.Setup(repo => repo.GetUserByIdAsync(userId))
            .ReturnsAsync((User)null);

        // Act
        var result = await _userService.GetUserByIdAsync(userId);

        // Assert
        Assert.Null(result);
    }
}

In this test:

  • Mock Setup: We create a mock of IUserRepository using Moq and set up the mock to return specific data when GetUserByIdAsync is called.
  • Arrange-Act-Assert Pattern: We follow the typical Arrange-Act-Assert pattern in writing the test:
    • Arrange: Prepare the necessary objects and mock behaviors.
    • Act: Call the method under test.
    • Assert: Verify the result is as expected.

Step 2: Running the Tests

Once the test is written, you can run the unit tests by executing:

dotnet test

This will run all the tests in your project, including the ones we just wrote.


Mocking Dependencies with Moq

In the examples above, we used Moq to mock the IUserRepository. Moq allows you to set up mock objects that simulate the behavior of real objects. You can also verify whether certain methods were called during testing.

Here’s how you can verify that a mock method was called:

_mockUserRepository.Verify(repo => repo.GetUserByIdAsync(It.IsAny<int>()), Times.Once);

This line verifies that GetUserByIdAsync was called exactly once during the test.


Conclusion

Unit testing is an essential practice in modern software development, especially in .NET Core. With xUnit and Moq, you can write effective unit tests that ensure the correctness of your application. By mocking dependencies, you can isolate the unit under test and ensure that your tests remain focused and reliable.

In this post, we’ve set up unit tests for a service class and used Moq to mock the dependencies, such as the IUserRepository. Following these practices will help you build more robust, maintainable, and testable applications in .NET Core.


Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *