ASP.NET Core
Ranjithkumar  

Do not resolve dependencies manually in ASP.NET Core Unit Testing

Dependency Injection (DI) is a core concept in ASP.NET Core, and it’s not just for production code. You should also leverage DI in your unit tests. Instead of manually resolving dependencies, using ServiceCollection to handle this is the recommended way. In this blog post, we’ll delve into why you should avoid manually resolving dependencies in unit testing and how to utilize ServiceCollection for a cleaner and more maintainable testing setup.

The Pitfall of Manual Dependency Resolution

Before we explore the right way to handle dependencies in unit tests, let’s discuss a common pitfall: manually resolving dependencies. I’ve seen people manually resolving dependencies when writing unit tests in ASP.NET Core, especially with controllers. This approach may look something like this:

public class MyControllerTests
{
    [Fact]
    public void MyController_Action_Should_Work()
    {
        // Arrange
        var myDependency = new MyDependency();
        var myService = new MyService(myDependency);
        var controller = new MyController(myService);

        // Act
        var result = controller.MyAction();

        // Assert
        // Perform assertions on the result
    }
}

While the above code technically tests the controller’s action, it comes with several issues:

  • Tight Coupling: Tests are tightly coupled to the specific implementation details of the code under test, making them brittle and prone to breakage when the implementation changes.
  • Complexity: As your application grows, manually managing dependencies can become unwieldy and complex, leading to code duplication across tests.
  • Maintenance Nightmare: If you need to make changes to how dependencies are resolved, you’ll have to update every test that manually resolves dependencies.

Leveraging ServiceCollection

ASP.NET Core’s ServiceCollection and built-in dependency injection container provide a much cleaner and more maintainable way to handle dependencies in unit tests. Here’s a step-by-step guide:

  • 1. Setting Up Your Test Project

In your test project, make sure to include a reference to the project containing the code you want to test.

  • 2. Configure ServiceCollection

In your test class, configure a new ServiceCollection instance in the test class’s constructor. You can set up your dependencies just as you do in your application’s Startup.cs file. For example:

public class MyServiceTests
{
    private readonly IServiceCollection _serviceCollection;
    
    public MyServiceTests()
    {
        _serviceCollection = new ServiceCollection();
        _serviceCollection.AddTransient<IMyDependency, MyDependency>();
        // Add other dependencies as needed
    }
}
  • 3. Create the Service Provider

After configuring the ServiceCollection, create a service provider using it:

var serviceProvider = _serviceCollection.BuildServiceProvider();
  • 4. Resolve Dependencies

You can now use the service provider to resolve dependencies in your test methods. For example:

[Fact]
public void MyService_Method_Should_Work()
{
    // Arrange
    var myService = serviceProvider.GetRequiredService<IMyService>();

    // Act
    var result = myService.MyMethod();

    // Assert
    Assert.True(result);
}

Benefits of Using ServiceCollection

  • Test Isolation: Tests are isolated from the actual implementation, making them less prone to breaking due to changes in the codebase.
  • Simplified Setup: You set up your dependencies in one place, reducing code duplication and making maintenance easier.
  • Improved Readability: Using the DI container enhances the readability of your tests. It’s clear which dependencies are used.
  • Consistency: You maintain consistency with your application’s DI configuration.

Wrapping Up

In summary, leveraging ServiceCollection and the built-in dependency injection container in ASP.NET Core for unit testing is a best practice. It helps you write more robust, maintainable, and clean unit tests. By avoiding manual dependency resolution, you keep your tests isolated and easier to manage.

Happy testing!

Leave A Comment