Web API Versioning and Testing
In the previous post, we have paid attention on our project structure and organizing the code in multiple layers to achieve better readability and easier maintanence in the future. Now we can focus on long-term sustainability through versioning and testing.
In this final part of the series, we will:
- Introduce API versioning so your app can evolve without breaking existing clients
- Add unit tests to validate service and controller behavior
API Versioning?
Versioning helps your API evolve over time without breaking existing clients. Let’s enable it.
Step 1: Install Required Package
In the Sample.Api
project, install:
dotnet add package Microsoft.AspNetCore.Mvc.Versioning
Step 2: Configure Versioning in Program.cs
In Program.cs
, add the following:
builder.Services.AddApiVersioning(options =>
{
options.AssumeDefaultVersionWhenUnspecified = true;
options.DefaultApiVersion = new ApiVersion(1, 0);
options.ReportApiVersions = true;
});
This:
-
Defaults to version 1.0 when none is specified
-
Adds version info in response headers
-
Prepares your API to support multiple versions side-by-side
You can version your API using:
-
URL segments (/v1/controller)
-
Query string (?api-version=1.0)
-
Headers (e.g., api-version: 1.0)
We’ll use URL-based versioning in this example.
Step 3: Create a Versioned Controller
In Sample.Api/Controllers
, decorate your controller like this:
[Route("api/v{version:apiVersion}/[controller]")]
[ApiVersion("1.0")]
[ApiController]
public class UserController : ControllerBase
{
....
That’s it—you’ve now added support for versioning via the URL.
Setting Up a Test Project
Now let’s set up unit testing using NUnit.
Step 1: Create a New Test Project
In the solution folder:
dotnet new nunit -n Sample.Api.Tests
Then add project references:
dotnet add Sample.Api.Tests reference Sample.Services
dotnet add Sample.Api.Tests reference Sample.Repositories
dotnet add Sample.Api.Tests reference Sample.DTO
dotnet add Sample.Api.Tests reference Sample.Entities
And install these packages:
dotnet add Sample.Api.Tests package Moq
dotnet add Sample.Api.Tests package Microsoft.AspNetCore.Mvc
Next, we can organize our tests in different folders, like /Services
, /Repositories
, /Controllers
Step 2: Writing Unit Tests for Services
Now, for the showing purpose, we can test UserService by mocking UserRepository:
[TestFixture]
public class UserTests
{
[Test]
public void GetUserByUsername_ReturnsDataFromRepo()
{
var mockRepo = new Mock<IUserRepository>();
mockRepo.Setup(r => r.GetUser("Test")).Returns(new User()
{
Id = 1,
Email = "test mail",
Username = "Test",
});
var service = new UserService(mockRepo.Object);
var user = service.GetUser("Test");
Assert.That(user.Email, Is.EqualTo("test mail"));
}
}
Here, we have shown one mocking example and how to isolate our service testing from depencency on repository. Similar can be done with controllers as well. For more details on testing and mocking, you can take a look at some of the previous posts for unit testing and mocking.
Summary
With versioning and testing in place, your API is now ready for real-world use:
-
Versioning allows the API to grow without breaking existing clients
-
Unit tests help you catch regressions early and keep logic robust
This wraps up our step-by-step guide to building a clean, testable, and production-ready .NET 9 Web API using best practices. Entire code can be found at my github repository.
Thanks for following the series!
Happy coding!