How to test minimal APIs in ASP.NET Core 6

ASP.NET Core 6 allows us to create APIs that include a bare minimum of files, features, and dependencies. Here’s how to test a minimal Web API.

Fighter pilot testing plane    82770200
Thinkstock

ASP.NET Core 6 introduces a simplified hosting model that can be used to implement lightweight APIs by eliminating the need to write the boilerplate code required in previous versions ASP.NET Core.

We discussed how to get started with minimal APIs, and how to use logging and dependency injection with minimal APIs, in previous articles here and here. This article discusses how we can test minimal APIs in ASP.NET Core 6.

To work with the code examples provided in this article, you should have Visual Studio 2022 installed in your system. If you don’t already have a copy, you can download Visual Studio 2022 here.

Create an ASP.NET Core Web API project in Visual Studio 2022

First off, let’s create an ASP.NET Core Web API project in Visual Studio 2022. Following these steps will create a new Web API project in Visual Studio 2022:

  1. Launch the Visual Studio 2022 IDE.
  2. Click on “Create new project.”
  3. In the “Create new project” window, select “ASP.NET Core Web API” from the list of templates displayed.
  4. Click Next.
  5. In the “Configure your new project” window, specify the name and location for the new project.
  6. Optionally check the “Place solution and project in the same directory” check box, depending on your preferences.
  7. Click Next.
  8. In the “Additional Information” window shown next, uncheck the check box that says “Use controllers…” since we’ll be using minimal APIs in this example. Leave the “Authentication Type” as “None” (default).
  9. Ensure that the check boxes “Enable Docker,” “Configure for HTTPS,” and “Enable Open API Support” are unchecked as we won’t be using any of those features here.
  10. Click Create.

We’ll use this ASP.NET Core 6 Web API project to test minimal APIs in the subsequent sections of this article.

Solution structure of the complete minimal Web API application

In this example, we’ll build two applications, named MinimalAPIDemo and MinimalAPIDemoTest. MinimalAPIDemo is the minimal ASP.NET Core 6 Web API that we’ll test, and MinimalAPITests is the test application. In our example, MinimalAPITests will contain one test method to test the MinimalAPIDemo API.

The completed solution structure would look like this:

minimal api demo 01 IDG

Figure 1. The complete solution structure for MinimalAPIDemo.

Create a minimal Web API in ASP.NET Core 6

Let’s now create our minimal Web API in ASP.NET Core 6. We’ll name it CustomerAPI. This Customer API will have the following files:

  • Customer (this represents the model class)
  • ICustomerRepository (this represents the customer repository interface)
  • CustomerRepository (this represents the customer repository class that implements the ICustomerRepository interface)

The Customer model class

Create a new file named Customer.cs and give it the following code.

namespace MinimalAPIDemo
{
    public class Customer
    {
        public int Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Address { get; set; }
        public string City { get; set; }
        public string Country { get; set; }
        public string Phone { get; set; }
    }
}

The ICustomerRepository interface

Now create a file named ICustomerRepository.cs and insert this code.

namespace MinimalAPIDemo
{
    public interface ICustomerRepository
    {
        public Task<List<Customer>> GetCustomers();
    }
}

The CustomerRepository class

Next create a file named CustomerRepository.cs and insert the following code.

namespace MinimalAPIDemo
{
    public class CustomerRepository : ICustomerRepository
    {
        private readonly List<Customer> _authors;
        public CustomerRepository()
        {
            _authors = new List<Customer>
            {
                new Customer
                {
                    Id = 1,
                    FirstName = "Joydip",
                    LastName = "Kanjilal",
                    Address = "ABC Hills",
                    City = "Hyderabad",
                    Country= "India",
                    Phone = "0123456789"
                },
                new Customer
                {
                    Id = 2,
                    FirstName = "Anand",
                    LastName = "Narayanaswamy",
                    Address = "XYZ Hills",
                    City = "Thiruvananthapuram",
                    Country= "India",
                    Phone = "1234567890"
                },
                new Customer
                {
                    Id = 3,
                    FirstName = "Charles",
                    LastName = "Fisher",
                    Address = "Dawson Road",
                    City = "New York ",
                    Country= "US",
                    Phone = "1234567890"
                }
            };
        }
        public async Task<List<Customer>> GetCustomers()
        {
            return await Task.FromResult(_authors);
        }
    }
}

The Program.cs file

Write the following code in the Program.cs file to create the endpoint.

app.MapGet("/customers", async (ICustomerRepository customerRepository) => await customerRepository.GetCustomers());

For the sake of simplicity, we’ll create just one endpoint in this example. Add an instance of type ICustomerRepository as a scoped service as shown below.

builder.Services.AddScoped<ICustomerRepository, CustomerRepository>();

You should also add a partial class named Program. This is because the Program.cs file will be compiled into a private class Program, which cannot be accessed from outside of the assembly.

public partial class Program { }

This partial class will make the Program class accessible to any project that references this assembly. The complete source code of the Program.cs file is given below for your reference.

using MinimalAPIDemo;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddScoped<ICustomerRepository, CustomerRepository>();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}
app.MapGet("/customers", async (ICustomerRepository customerRepository) => await customerRepository.GetCustomers());
app.Run();
public partial class Program { }

Create a minimal Web API test project in ASP.NET Core 6

Create a Xunit test project named MinimalAPIDemo.Tests and rename the default unit test file to MinimalAPITests.cs. Here is where you should write your test methods. In this example, we’ll create only one test method to test the endpoint we created earlier.

Now let’s write a test method named GetAllCustomersTest with the following code.

[Fact]
public async void GetAllCustomersTest()
{
   await using var application = new WebApplicationFactory<Program>();
   using var client = application.CreateClient();
   var response = await client.GetAsync("/customers");
   var data = await response.Content.ReadAsStringAsync();
   Assert.Equal(HttpStatusCode.OK, response.StatusCode);
}

The complete source code of the MinimalAPITests class is given below for your reference.

using Microsoft.AspNetCore.Mvc.Testing;
using System.Net;
using Xunit;
namespace MinimalAPIDemo.Tests
{
    public class MinimalAPITests
    {
        [Fact]
        public async void GetAllCustomersTest()
        {
            await using var application = new
            WebApplicationFactory<Program>();
            using var client = application.CreateClient();
            var response = await client.GetAsync("/customers");
            var data = await response.Content.ReadAsStringAsync();
            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
        }
    }
}

When you execute the test method, the response of the /customers endpoint should appear as displayed in Figure 2 below.

minimal api demo 02 IDG

Figure 2. The MinimalAPITests test method in action.

This being a minimal implementation, we’ve not used a database or a data context, but merely a simple repository class with a few static data elements—just enough to illustrate how we can build minimal APIs and test them in ASP.NET Core 6. I’ll have more to say on minimal APIs in future posts here.

Copyright © 2022 IDG Communications, Inc.