# Write your first test

<PivotSelector
    title="Select your testing framework"
    key="testing-framework"
    options={[
        { id: "xunit", title: "xUnit.net" },
        { id: "mstest", title: "MSTest" },
        { id: "nunit", title: "NUnit" },
    ]}
/>

In this article, you'll learn how to create a test project, write C# tests, and run them for your Aspire solutions. These aren't unit tests—they're functional and integration tests that validate how your distributed application components work together. Aspire provides testing project templates for xUnit.net, MSTest, and NUnit frameworks, each including a sample test to help you get started quickly.

## Conceptualizing distributed app testing

Before you start testing your Aspire solutions, you'll need the [📦 Aspire.Hosting.Testing](https://www.nuget.org/packages/Aspire.Hosting.Testing) NuGet package. This powerful package provides the `DistributedApplicationTestingBuilder` class—your gateway to creating a test host for distributed applications.

Think of the `DistributedApplicationTestingBuilder` as a test harness that launches your AppHost project with built-in instrumentation. This gives you precise control to access and manipulate the host throughout its lifecycle. You'll work with familiar Aspire types like `IDistributedApplicationBuilder` and `DistributedApplication` to build and start your [AppHost](/get-started/app-host/), making your tests feel natural and intuitive.

## Create a test project

To create an Aspire test project, use the testing project template. When starting a new Aspire project, both IDE and CLI tooling prompts you to create a test project for some templates. To add a test project to an existing Aspire solution, use the [`dotnet new`](https://learn.microsoft.com/dotnet/core/tools/dotnet-new) command:

<Pivot id="xunit">

```bash
dotnet new aspire-xunit -o xUnit.Tests
```

</Pivot>
<Pivot id="mstest">

```bash
dotnet new aspire-mstest -o MSTest.Tests
```

</Pivot>
<Pivot id="nunit">

```bash
dotnet new aspire-nunit -o NUnit.Tests
```

</Pivot>

Change directory to the newly created test project:

<Pivot id="xunit">

```bash
cd xUnit.Tests
```

</Pivot>
<Pivot id="mstest">

```bash
cd MSTest.Tests
```

</Pivot>
<Pivot id="nunit">

```bash
cd NUnit.Tests
```

</Pivot>

After adding the test project to your Aspire solution, add a project reference to the target AppHost. For example, if your Aspire solution contains an AppHost project named `AspireApp.AppHost`, add a project reference to it from the test project:

<Pivot id="xunit">

```bash
dotnet reference add ../AspireApp.AppHost/AspireApp.AppHost.csproj --project xUnit.Tests.csproj
```

</Pivot>
<Pivot id="mstest">

```bash
dotnet reference add ../AspireApp.AppHost/AspireApp.AppHost.csproj --project MSTest.Tests.csproj
```

</Pivot>
<Pivot id="nunit">

```bash
dotnet reference add ../AspireApp.AppHost/AspireApp.AppHost.csproj --project NUnit.Tests.csproj
```

</Pivot>

Finally, you can uncomment out the `IntegrationTest1.cs` file in the test project to explore the sample test.

## Explore the test project

The following example test project was created as part of the **Blazor & Minimal API starter** template. If you're unfamiliar with it, see [Build your first app—C#](/get-started/first-app/?lang=csharp). The Aspire test project takes a project reference dependency on the target AppHost. Consider the template project:

<Pivot id="xunit">

```xml title="xUnit.Tests.csproj"
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net10.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    <IsPackable>false</IsPackable>
    <IsTestProject>true</IsTestProject>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Aspire.Hosting.Testing" Version="13.1.0" />
    <PackageReference Include="coverlet.collector" Version="6.0.4" />
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
    <PackageReference Include="xunit" Version="2.9.3" />
    <PackageReference Include="xunit.runner.visualstudio" Version="3.1.4" />
  </ItemGroup>

  <ItemGroup>
    <ProjectReference Include="..\AspireApp.AppHost\AspireApp.AppHost.csproj" />
  </ItemGroup>

  <ItemGroup>
    <Using Include="System.Net" />
    <Using Include="Microsoft.Extensions.DependencyInjection" />
    <Using Include="Aspire.Hosting.ApplicationModel" />
    <Using Include="Aspire.Hosting.Testing" />
    <Using Include="Xunit" />
  </ItemGroup>

</Project>
```

</Pivot>
<Pivot id="mstest">

```xml title="MSTest.Tests.csproj"
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net10.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    <IsPackable>false</IsPackable>
    <IsTestProject>true</IsTestProject>
    <EnableMSTestRunner>true</EnableMSTestRunner>
    <OutputType>Exe</OutputType>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Aspire.Hosting.Testing" Version="13.1.0" />
    <PackageReference Include="MSTest" Version="3.10.2" />
  </ItemGroup>

  <ItemGroup>
    <ProjectReference Include="..\AspireApp.AppHost\AspireApp.AppHost.csproj" />
  </ItemGroup>

  <ItemGroup>
    <Using Include="System.Net" />
    <Using Include="Microsoft.Extensions.DependencyInjection" />
    <Using Include="Aspire.Hosting.ApplicationModel" />
    <Using Include="Aspire.Hosting.Testing" />
    <Using Include="Microsoft.VisualStudio.TestTools.UnitTesting" />
  </ItemGroup>

</Project>
```

</Pivot>
<Pivot id="nunit">

```xml title="NUnit.Tests.csproj"
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net10.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    <IsPackable>false</IsPackable>
    <IsTestProject>true</IsTestProject>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Aspire.Hosting.Testing" Version="13.1.0" />
    <PackageReference Include="coverlet.collector" Version="6.0.4" />
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
    <PackageReference Include="NUnit" Version="4.4.0" />
    <PackageReference Include="NUnit.Analyzers" Version="4.10.0" />
    <PackageReference Include="NUnit3TestAdapter" Version="4.6.0" />
  </ItemGroup>

  <ItemGroup>
    <ProjectReference Include="..\AspireApp.AppHost\AspireApp.AppHost.csproj" />
  </ItemGroup>

  <ItemGroup>
    <Using Include="System.Net" />
    <Using Include="Microsoft.Extensions.DependencyInjection" />
    <Using Include="Aspire.Hosting.ApplicationModel" />
    <Using Include="Aspire.Hosting.Testing" />
    <Using Include="NUnit.Framework" />
  </ItemGroup>

</Project>
```

</Pivot>

The preceding project file is fairly standard. There's a `PackageReference` to the [📦 Aspire.Hosting.Testing](https://www.nuget.org/packages/Aspire.Hosting.Testing) NuGet package, which includes the required types to write tests for Aspire projects.

The template test project includes an `IntegrationTest1` class with a single test. The test verifies the following scenario:

- The AppHost is successfully created and started.
- The `webfrontend` resource is available and running.
- An HTTP request can be made to the `webfrontend` resource and returns a successful response (HTTP 200 OK).

Consider the following test class:

<Pivot id="xunit">

```csharp title="IntegrationTest1.cs"
using Microsoft.Extensions.Logging;

namespace xUnit.Tests.Tests;

public class IntegrationTest1
{
    private static readonly TimeSpan DefaultTimeout = TimeSpan.FromSeconds(30);

    [Fact]
    public async Task GetWebResourceRootReturnsOkStatusCode()
    {
        // Arrange
        var cancellationToken = CancellationToken.None;
        var appHost = await DistributedApplicationTestingBuilder
            .CreateAsync<Projects.AspireApp_AppHost>(cancellationToken);
        appHost.Services.AddLogging(logging =>
        {
            logging.SetMinimumLevel(LogLevel.Debug);
            // Override the logging filters from the app's configuration
            logging.AddFilter(appHost.Environment.ApplicationName, LogLevel.Debug);
            logging.AddFilter("Aspire.", LogLevel.Debug);
        });
        appHost.Services.ConfigureHttpClientDefaults(clientBuilder =>
        {
            clientBuilder.AddStandardResilienceHandler();
        });
    
        await using var app = await appHost.BuildAsync(cancellationToken)
            .WaitAsync(DefaultTimeout, cancellationToken);
        await app.StartAsync(cancellationToken)
            .WaitAsync(DefaultTimeout, cancellationToken);
    
        // Act
        using var httpClient = app.CreateHttpClient("webfrontend");
        await app.ResourceNotifications.WaitForResourceHealthyAsync(
            "webfrontend", cancellationToken)
            .WaitAsync(DefaultTimeout, cancellationToken);
        using var response = await httpClient.GetAsync("/", cancellationToken);
    
        // Assert
        Assert.Equal(HttpStatusCode.OK, response.StatusCode);
    }
}
```

</Pivot>
<Pivot id="mstest">

```csharp title="IntegrationTest1.cs"
using Microsoft.Extensions.Logging;

namespace MSTest.Tests;

[TestClass]
public class IntegrationTest1
{
    public TestContext TestContext { get; set; }

    private static readonly TimeSpan DefaultTimeout = TimeSpan.FromSeconds(30);

    [TestMethod]
    public async Task GetWebResourceRootReturnsOkStatusCode()
    {
        // Arrange
        var cancellationToken = TestContext.CancellationTokenSource.Token;
        var appHost = await DistributedApplicationTestingBuilder
            .CreateAsync<Projects.AspireApp_AppHost>();
        appHost.Services.AddLogging(logging =>
        {
            logging.SetMinimumLevel(LogLevel.Debug);
            // Override the logging filters from the app's configuration
            logging.AddFilter(appHost.Environment.ApplicationName, LogLevel.Debug);
            logging.AddFilter("Aspire.", LogLevel.Debug);
        });
        appHost.Services.ConfigureHttpClientDefaults(clientBuilder =>
        {
            clientBuilder.AddStandardResilienceHandler();
        });
    
        await using var app = await appHost.BuildAsync(cancellationToken)
            .WaitAsync(DefaultTimeout, cancellationToken);
        await app.StartAsync(cancellationToken)
            .WaitAsync(DefaultTimeout, cancellationToken);
    
        // Act
        using var httpClient = app.CreateHttpClient("webfrontend");
        await app.ResourceNotifications.WaitForResourceHealthyAsync(
            "webfrontend", cancellationToken)
            .WaitAsync(DefaultTimeout, cancellationToken);
        using var response = await httpClient.GetAsync("/", cancellationToken);
    
        // Assert
        Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
    }
}
```

</Pivot>
<Pivot id="nunit">

```csharp title="IntegrationTest1.cs"
using Microsoft.Extensions.Logging;

namespace NUnit.Tests;

public class IntegrationTest1
{
    private static readonly TimeSpan DefaultTimeout = TimeSpan.FromSeconds(30);

    [Test]
    public async Task GetWebResourceRootReturnsOkStatusCode()
    {
        // Arrange
        using var cts = new CancellationTokenSource(DefaultTimeout);
        var cancellationToken = cts.Token;
        var appHost = await DistributedApplicationTestingBuilder
            .CreateAsync<Projects.AspireApp_AppHost>();
        appHost.Services.AddLogging(logging =>
        {
            logging.SetMinimumLevel(LogLevel.Debug);
            // Override the logging filters from the app's configuration
            logging.AddFilter(appHost.Environment.ApplicationName, LogLevel.Debug);
            logging.AddFilter("Aspire.", LogLevel.Debug);
        });
        appHost.Services.ConfigureHttpClientDefaults(clientBuilder =>
        {
            clientBuilder.AddStandardResilienceHandler();
        });
    
        await using var app = await appHost.BuildAsync(cancellationToken)
            .WaitAsync(DefaultTimeout, cancellationToken);
        await app.StartAsync(cancellationToken)
            .WaitAsync(DefaultTimeout, cancellationToken);
    
        // Act
        using var httpClient = app.CreateHttpClient("webfrontend");
        await app.ResourceNotifications.WaitForResourceHealthyAsync(
            "webfrontend", cancellationToken)
            .WaitAsync(DefaultTimeout, cancellationToken);
        using var response = await httpClient.GetAsync("/", cancellationToken);
    
        // Assert
        Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK));
    }
}
```

</Pivot>

The preceding code:

- Relies on the `DistributedApplicationTestingBuilder.CreateAsync` API to asynchronously create the AppHost.
- The `appHost` is an instance of `IDistributedApplicationTestingBuilder` that represents the AppHost.
- The `appHost` instance has its service collection configured with logging and the standard HTTP resilience handler. For more information, see [Build resilient HTTP apps: Key development patterns](https://learn.microsoft.com/dotnet/core/resilience/http-resilience).
- The `appHost` has its `BuildAsync` method invoked, which returns the `DistributedApplication` instance as the `app`.
- The `app` is started asynchronously.
- An `HttpClient` is created for the `webfrontend` resource by calling `app.CreateHttpClient`.
- The `app.ResourceNotifications` is used to wait for the `webfrontend` resource to be healthy.
- A simple HTTP GET request is made to the root of the `webfrontend` resource.
- The test asserts that the response status code is `OK`.

## Test resource environment variables

To further test resources and their expressed dependencies in your Aspire solution, you can assert that environment variables are injected correctly. The following example demonstrates how to test that the `webfrontend` resource has an HTTPS environment variable that resolves to the `apiservice` resource:

<Pivot id="xunit">

```csharp title="EnvVarTests.cs"
using Aspire.Hosting;
using Microsoft.Extensions.Logging.Abstractions;

namespace Tests;

public class EnvVarTests
{
    [Fact]
    public async Task WebResourceEnvVarsResolveToApiService()
    {
        // Arrange
        var builder = await DistributedApplicationTestingBuilder
            .CreateAsync<Projects.AspireApp_AppHost>();

        var frontend = builder.CreateResourceBuilder<ProjectResource>("webfrontend");

        // Act
        var executionConfiguration = await ExecutionConfigurationBuilder.Create(frontend.Resource)
            .WithEnvironmentVariablesConfig()
            .BuildAsync(new(DistributedApplicationOperation.Publish), NullLogger.Instance, CancellationToken.None)
            .ConfigureAwait(true);

        var envVars = executionConfiguration.EnvironmentVariables.ToDictionary();

        // Assert
        Assert.Contains(envVars, static (kvp) =>
        {
            var (key, value) = kvp;

            return key is "APISERVICE_HTTPS"
                && value is "{apiservice.bindings.https.url}";
        });
    }
}
```

</Pivot>
<Pivot id="mstest">

```csharp title="EnvVarTests.cs"
using Aspire.Hosting;
using Microsoft.Extensions.Logging.Abstractions;

namespace Tests;

[TestClass]
public class EnvVarTests
{
    [TestMethod]
    public async Task WebResourceEnvVarsResolveToApiService()
    {
        // Arrange
        var builder = await DistributedApplicationTestingBuilder
            .CreateAsync<Projects.AspireApp_AppHost>();

        var frontend = builder.CreateResourceBuilder<ProjectResource>("webfrontend");

        // Act
        var executionConfiguration = await ExecutionConfigurationBuilder.Create(frontend.Resource)
            .WithEnvironmentVariablesConfig()
            .BuildAsync(new(DistributedApplicationOperation.Publish), NullLogger.Instance, CancellationToken.None)
            .ConfigureAwait(true);

        var envVars = executionConfiguration.EnvironmentVariables.ToDictionary();

        // Assert
        CollectionAssert.Contains(envVars,
            new KeyValuePair<string, string>(
                key: "APISERVICE_HTTPS",
                value: "{apiservice.bindings.https.url}"));
    }
}
```

</Pivot>
<Pivot id="nunit">

```csharp title="EnvVarTests.cs"
using Aspire.Hosting;
using Microsoft.Extensions.Logging.Abstractions;

namespace Tests;

public class EnvVarTests
{
    [Test]
    public async Task WebResourceEnvVarsResolveToApiService()
    {
        // Arrange
        var builder = await DistributedApplicationTestingBuilder
            .CreateAsync<Projects.AspireApp_AppHost>();

        var frontend = builder.CreateResourceBuilder<ProjectResource>("webfrontend");

        // Act
        var executionConfiguration = await ExecutionConfigurationBuilder.Create(frontend.Resource)
            .WithEnvironmentVariablesConfig()
            .BuildAsync(new(DistributedApplicationOperation.Publish), NullLogger.Instance, CancellationToken.None)
            .ConfigureAwait(true);

        var envVars = executionConfiguration.EnvironmentVariables.ToDictionary();

        // Assert
        Assert.That(envVars, Does.Contain(
            new KeyValuePair<string, string>(
                key: "APISERVICE_HTTPS",
                value: "{apiservice.bindings.https.url}")));
    }
}
```

</Pivot>

The preceding code:

- Relies on the `DistributedApplicationTestingBuilder.CreateAsync` API to asynchronously create the AppHost.
- The `builder` instance is used to retrieve an `IResourceWithEnvironment` instance named "webfrontend" from the `Resources` property.
- Builds an `ExecutionConfiguration` for the `webfrontend` resource using `ExecutionConfigurationBuilder`, explicitly enabling environment variable configuration via `WithEnvironmentVariablesConfig`.
- Calls `BuildAsync` with `DistributedApplicationOperation.Publish` to generate the environment variables that will be published for the resource, including unresolved binding expressions.
- With the returned environment variables, the test asserts that the `webfrontend` resource has an HTTPS environment variable that resolves to the `apiservice` resource.

## Capture logs from tests

When writing tests for your Aspire solutions, you might want to capture and view logs to help with debugging and monitoring test execution. The `DistributedApplicationTestingBuilder` provides access to the service collection, allowing you to configure logging for your test scenarios.

### Configure logging providers

To capture logs from your tests, use the `AddLogging` method on the `builder.Services` to configure logging providers specific to your testing framework:

<Pivot id="xunit">

```csharp title="LoggingTest.cs"
using Microsoft.Extensions.Logging;

namespace Tests;

public class LoggingTest
{
    [Fact]
    public async Task GetWebResourceRootReturnsOkStatusCodeWithLogging()
    {
        // Arrange
        var builder = await DistributedApplicationTestingBuilder
            .CreateAsync<Projects.AspireApp_AppHost>();

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

        // Configure logging to capture test execution logs
        builder.Services.AddLogging(logging => logging
            .AddConsole() // Outputs logs to console
            .AddFilter("Default", LogLevel.Information)
            .AddFilter("Microsoft.AspNetCore", LogLevel.Warning)
            .AddFilter("Aspire.Hosting.Dcp", LogLevel.Warning));

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

        await app.StartAsync();

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

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

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

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

</Pivot>
<Pivot id="mstest">

```csharp title="LoggingTest.cs"
using Microsoft.Extensions.Logging;

namespace Tests;

[TestClass]
public class LoggingTest
{
    [TestMethod]
    public async Task GetWebResourceRootReturnsOkStatusCodeWithLogging()
    {
        // Arrange
        var builder = await DistributedApplicationTestingBuilder
            .CreateAsync<Projects.AspireApp_AppHost>();

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

        // Configure logging to capture test execution logs
        builder.Services.AddLogging(logging => logging
            .AddConsole() // Outputs logs to console
            .AddFilter("Default", LogLevel.Information)
            .AddFilter("Microsoft.AspNetCore", LogLevel.Warning)
            .AddFilter("Aspire.Hosting.Dcp", LogLevel.Warning));

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

        await app.StartAsync();

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

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

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

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

</Pivot>
<Pivot id="nunit">

```csharp title="LoggingTest.cs"
using Microsoft.Extensions.Logging;

namespace Tests;

public class LoggingTest
{
    [Test]
    public async Task GetWebResourceRootReturnsOkStatusCodeWithLogging()
    {
        // Arrange
        var builder = await DistributedApplicationTestingBuilder
            .CreateAsync<Projects.AspireApp_AppHost>();

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

        // Configure logging to capture test execution logs
        builder.Services.AddLogging(logging => logging
            .AddConsole() // Outputs logs to console
            .AddFilter("Default", LogLevel.Information)
            .AddFilter("Microsoft.AspNetCore", LogLevel.Warning)
            .AddFilter("Aspire.Hosting.Dcp", LogLevel.Warning));

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

        await app.StartAsync();

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

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

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

        // Assert
        Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK));
    }
}
```

</Pivot>

### Configure log filters

Since the _appsettings.json_ configuration from your application isn't automatically replicated in test projects, you need to explicitly configure log filters. This is important to avoid excessive logging from infrastructure components that might overwhelm your test output. The following snippet explicitly configures log filters:

```csharp
builder.Services.AddLogging(logging => logging
    .AddFilter("Default", LogLevel.Information)
    .AddFilter("Microsoft.AspNetCore", LogLevel.Warning)
    .AddFilter("Aspire.Hosting.Dcp", LogLevel.Warning));
```

The preceding configuration:

- Sets the default log level to `Information` for most application logs.
- Reduces noise from ASP.NET Core infrastructure by setting it to `Warning` level.
- Limits Aspire hosting infrastructure logs to `Warning` level to focus on application-specific logs.

### Popular logging packages

Different testing frameworks have different logging provider packages available to assist with managing logging during test execution:

<Pivot id="xunit">

xUnit.net doesn't capture log output from tests as test output. Tests must [use the `ITestOutputHelper` interface](https://xunit.net/docs/capturing-output) to achieve this.

For xUnit.net, consider using one of these logging packages:

- [📦 MartinCostello.Logging.XUnit](https://www.nuget.org/packages/MartinCostello.Logging.XUnit) - Outputs `ILogger` logs to `ITestOutputHelper` output.
- [📦 Xunit.DependencyInjection.Logging](https://www.nuget.org/packages/Xunit.DependencyInjection.Logging) - Integrates with xUnit.net's dependency injection.
- [📦 Serilog.Extensions.Logging.File](https://www.nuget.org/packages/Serilog.Extensions.Logging.File) - Writes logs to files.
- [📦 Microsoft.Extensions.Logging.Console](https://www.nuget.org/packages/Microsoft.Extensions.Logging.Console) - Outputs logs to console.

</Pivot>
<Pivot id="mstest">

For MSTest, consider using one of these logging packages:

- [📦 Serilog.Extensions.Logging.File](https://www.nuget.org/packages/Serilog.Extensions.Logging.File) - Writes logs to files.
- [📦 Microsoft.Extensions.Logging.Console](https://www.nuget.org/packages/Microsoft.Extensions.Logging.Console) - Outputs logs to console.

</Pivot>
<Pivot id="nunit">

For NUnit, consider using one of these logging packages:

- [📦 Extensions.Logging.NUnit](https://www.nuget.org/packages/Extensions.Logging.NUnit) - Integrates with NUnit framework.
- [📦 Serilog.Extensions.Logging.File](https://www.nuget.org/packages/Serilog.Extensions.Logging.File) - Writes logs to files.
- [📦 Microsoft.Extensions.Logging.Console](https://www.nuget.org/packages/Microsoft.Extensions.Logging.Console) - Outputs logs to console.

</Pivot>

## Summary

The Aspire testing project template makes it easier to create test projects for Aspire solutions. The template project includes a sample test that you can use as a starting point for your tests. The `DistributedApplicationTestingBuilder` follows a familiar pattern to the `WebApplicationFactory<T>` in ASP.NET Core. It allows you to create a test host for your distributed application and run tests against it.

Finally, when using the `DistributedApplicationTestingBuilder` all resource logs are redirected to the `DistributedApplication` by default. The redirection of resource logs enables scenarios where you want to assert that a resource is logging correctly.