Unit Testing Hosted Services in ASP.NET WEB API
WebAPI
19 Articles
Table of Contents
What we gonna do?
In this article, let's learn about how to unit test Hosted Services in WebAPI in ASP.NET Core.
In ASP.NET Core, hosted services plays a vital role in simplifying background jobs which needs to run periodically to perform operations. Most common use cases include:
- Processing uploaded excel in background
- Sending emails in background
- Performing data migration
- Syncing data between two data sources
- Other long running operations, etc
To know more about Hosted Service or Background Service is outside the scope of this article. I'll write a separate article on Background Services in ASP.NET Core. For now lets understand walkthrough how to use Hosted Service.
Why we gonna do?
When writing software, we want to ensure that the code is covered by tests, which verify the required behavior and catch any regressions. Unit testing is a crucial practice in software development as it helps identify issues early in the development process. When it comes to service registration, unit testing offers the following benefits:
- Validation: Unit tests verify that the necessary services are registered correctly, avoiding runtime errors caused by missing or misconfigured dependencies.
- Refactoring: Unit tests provide a safety net when refactoring code by ensuring that service registration remains intact during code changes.
- Documentation: Well-written unit tests serve as living documentation, illustrating how services should be registered and ensuring consistency across the application.
Note: If you have not done so already, I recommend you read the article on Implementing TDD in C# .Net.
How we gonna do?
We are going to write unit tests for the Data Migration Hosted Service which we used in our previous article on Perform Background Workloads in Hosted Service using Channels in ASP.NET Web API. Here is the quick reference of the hosted service used in that article.
Code Sample - Data Migration Hosted Service
To unit test the DataMigrationService Hosted Service, follow these steps:
- Create a new test class, let's call it HostedServiceTests, and add a test method using the [Fact] attribute.
- In the test method, instantiate a DataMigrationChannel which we used in previous article and ServiceCollection from the Microsoft.Extensions.DependencyInjection namespace. This collection will act as the container for our services.
- Use Moq to Mock the IUnitOfWork and add it to the ServiceCollection and call BuildServiceProvider() to build the ServiceProvider instance.
- Finally let's use NullLogger<DataMigrationService>.Instance from Microsoft.Extensions.Logging.Abstractions namespace instead of Mocking it as we are not going to test the logger. Moreover mocking Logger is a complex step.
- Next Call the MigrateData method in the DataMigrationChannel object to add message to the channel.
- Then, instantiate the DataMigrationService class with the above instantiated parameters and call the StartAsync method with default CancellationToken to start the service.
- Now call ExecuteTask from the DataMigrationService class to execute the task. This will make the ExecuteAsync of actual background service to run.
- Perform assertions using the IsCompletedSuccessfully result on the ExecuteTask of DataMigrationService. Check for its success.
- Additionally, verify IUnitOfWork using Moq Verify methods.
Code Sample - Unit Testing Hosted Service in ASP.NET Web API
Here is an another examples of background service using TimeProvider which uses timer to Sync data attribute regular interval. Let's see how to unit test this service.
Code Sample - Data Syncing Hosted Service
To unit test the DataSyncService Hosted Service, follow these steps:
- Create a new test class, let's call it HostedServiceTests, and add a test method using the [Fact] attribute.
- In the test method, instantiate a FakeTimeProvider To adjust time and test. This is available from Microsoft.Extensions.TimeProvider.Testing namespace.
- Finally let's use FakeLogger<DataSyncService> from Microsoft.Extensions.Diagnostics.Testing namespace instead of Mocking it as we are going to test the logger. Moreover mocking Logger is a complex step.
- Then, instantiate the DataSyncService class with the above instantiated parameters and call the StartAsync method with default CancellationToken to start the service.
- Now call ExecuteTask from the DataSyncService class to execute the task. This will make the ExecuteAsync of actual background service to run.
- Now adjust the time using by calling Advance from FakeTimeProvider. This will execute the SyncData callback passed to the periodic timer in the DataSyncService Background Service.
- Perform assertions using the IsCompletedSuccessfully result on the ExecuteTask of DataSyncService. Check for its success.
- Additionally, make assertions as per your needs.
Code Sample - Unit Testing Hosted Service in ASP.NET Web API
By executing above test we can validate background services in ASP.NET Core apps. The same can be used to validate worker services in dotnet.
Summary
Unit testing hosted services in ASP.NET Core is a crucial step to ensure that they are working as expected. By writing unit tests, you can validate behavior, identify issues early on, and maintain a reliable and robust application. The examples and techniques covered in this article provide a solid foundation for performing unit tests on hosted services, promoting software quality and maintainability in ASP.NET Core applications.