# API Testing with Aspire

Learn how to write API integration tests using Aspire's `DistributedApplicationTestingBuilder`.

[TOC]

## 📋 Overview

| Property          | Value                                                           |
| ----------------- | --------------------------------------------------------------- |
| **Goal**          | Test API endpoints using Aspire's distributed testing framework |
| **Prerequisites** | .NET 10 SDK, Aspire project with AppHost                        |
| **Time**          | 15 minutes                                                      |

This guide demonstrates how to create integration tests for your API endpoints using the `Aspire.Hosting.Testing` library.

## 🔗 Related Resources

- [Aspire Testing Documentation](https://learn.microsoft.com/en-us/dotnet/aspire/testing/overview)
- [Web Integration Testing with Playwright](./web-integration-testing.md)

---

## 📦 Required Packages

Add the following NuGet packages to your test project:

```xml
<PackageReference Include="Aspire.Hosting.Testing" />
<PackageReference Include="Microsoft.Extensions.Http.Resilience" />
<PackageReference Include="xunit" />
```

---

## 🧪 Test Structure

### Namespaces

```csharp
using Aspire.Hosting.Testing;
using Microsoft.Extensions.DependencyInjection;
using System.Net;
```

### Test Class

```csharp
public class ApiTests
{
    // Your test methods go here
}
```

---

## 📝 Example: Testing API Root Endpoint

This test verifies that the root endpoint (`/`) returns an HTTP 200 OK status code.

### Steps

1. **Arrange**: Create and configure the distributed application
2. **Act**: Send HTTP request to the API
3. **Assert**: Verify the response status code

### Code

```csharp
[Fact]
public async Task Get_Root_Returns_OkStatusCode()
{
    // Arrange
    var builder = await DistributedApplicationTestingBuilder
        .CreateAsync<Projects.YourAppHost_AppHost>();

    builder.Services.ConfigureHttpClientDefaults(clientBuilder =>
    {
        clientBuilder.AddStandardResilienceHandler();
    });

    await using var app = await builder.BuildAsync();

    await app.StartAsync();

    // Act
    var httpClient = app.CreateHttpClient("api");

    using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30));
    await app.ResourceNotifications.WaitForResourceHealthyAsync(
        "api",
        cts.Token);

    var response = await httpClient.GetAsync("/");

    // Assert
    Assert.Equal(HttpStatusCode.OK, response.StatusCode);
}
```

---

## 🔑 Key Concepts

### DistributedApplicationTestingBuilder

The `DistributedApplicationTestingBuilder` creates an isolated instance of your Aspire AppHost for testing:

```csharp
var builder = await DistributedApplicationTestingBuilder
    .CreateAsync<Projects.YourAppHost_AppHost>();
```

### HTTP Client Configuration

Configure resilience handlers to handle transient failures during testing:

```csharp
builder.Services.ConfigureHttpClientDefaults(clientBuilder =>
{
    clientBuilder.AddStandardResilienceHandler();
});
```

### Resource Health Checks

Wait for resources to be healthy before testing:

```csharp
await app.ResourceNotifications.WaitForResourceHealthyAsync(
    "api",
    cts.Token);
```

---

## 💡 Best Practices

1. **Use timeouts**: Always use `CancellationTokenSource` to prevent tests from hanging
2. **Wait for health**: Use `WaitForResourceHealthyAsync` before making requests
3. **Configure resilience**: Add standard resilience handlers for transient failure handling
4. **Dispose properly**: Use `await using` to ensure proper cleanup

---

## 🔗 Related Documentation

- [Aspire Overview](../../../reference/tools/aspire.md)
- [Web Integration Testing with Playwright](./web-integration-testing.md)
- [Integration Test Environment Variables](./integration-test-environment-variables.md)
- [Aspire Playwright Foundry Example](../../../foundry/aspire-playwright.md)
