Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
I den här artikeln får du lära dig hur du skapar ett testprojekt, skriver tester och kör dem för dina Aspire lösningar. Testerna i den här artikeln är inte enhetstester, utan snarare funktions- eller integreringstester. Aspire innehåller flera varianter av testprojektmallar som du kan använda för att testa dina Aspire resursberoenden – och deras kommunikation. Testprojektmallarna är tillgängliga för MSTest, NUnit och xUnit.net testramverk och innehåller ett exempeltest som du kan använda som utgångspunkt för dina tester.
Testprojektmallarna Aspire förlitar sig på 📦Aspire. Hosting.Testing NuGet-paket. Det här paketet exponerar klassen DistributedApplicationTestingBuilder, som används för att skapa en testvärd för ditt distribuerade program. Den distribuerade programtestverktyget startar ditt AppHost-projekt med instrumentationskrokar så att du kan komma åt och manipulera värden i olika skeden av dess livslängd. I synnerhet DistributedApplicationTestingBuilder ger dig åtkomst till IDistributedApplicationBuilder och DistributedApplication klass för att skapa och starta AppHost.
Skapa ett testprojekt
Det enklaste sättet att skapa ett Aspire testprojekt är att använda testprojektmallen. Om du startar ett nytt Aspire projekt och vill inkludera testprojekt stöder verktygenVisual Studio det alternativet. Om du lägger till ett testprojekt i ett befintligt Aspire projekt kan du använda dotnet new kommandot för att skapa ett testprojekt:
dotnet new aspire-xunit
dotnet new aspire-mstest
dotnet new aspire-nunit
För mer information, se dokumentationen för kommandot .NET CLI dotnet new.
Utforska testprojektet
Följande exempeltestprojekt skapades som en del av mallen Aspire Startprogram . Om du inte känner till det kan du läsa Snabbstart: Skapa ditt första Aspire projekt. Testprojektet Aspire har ett projektreferensberoende av den målhostade AppHost. Överväg mallprojektet:
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net9.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    <IsPackable>false</IsPackable>
    <IsTestProject>true</IsTestProject>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Aspire.Hosting.Testing" Version="9.5.2" />
    <PackageReference Include="coverlet.collector" Version="6.0.4" />
    <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="9.0.10" />
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.0" />
    <PackageReference Include="xunit" Version="2.9.3" />
    <PackageReference Include="xunit.runner.visualstudio" Version="3.1.5" />
  </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>
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net9.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    <IsPackable>false</IsPackable>
    <IsTestProject>true</IsTestProject>
  </PropertyGroup>
  <PropertyGroup>
    <EnableMSTestRunner>true</EnableMSTestRunner>
    <OutputType>Exe</OutputType>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Aspire.Hosting.Testing" Version="9.5.2" />
    <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="9.0.10" />
    <PackageReference Include="MSTest" Version="4.0.1" />
  </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>
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net9.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    <IsPackable>false</IsPackable>
    <IsTestProject>true</IsTestProject>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Aspire.Hosting.Testing" Version="9.5.2" />
    <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="9.0.10" />
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.0" />
    <PackageReference Include="NUnit" Version="4.4.0" />
    <PackageReference Include="NUnit.Analyzers" Version="4.11.0" />
    <PackageReference Include="NUnit3TestAdapter" Version="5.2.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>
Den föregående projektfilen är ganska standard. Det finns en PackageReference till 📦Aspire.Hosting.Testing NuGet-paketet, som innehåller de typer som krävs för att skriva tester för Aspire projekt.
Malltestprojektet innehåller en IntegrationTest1-klass med ett enda test. Testet verifierar följande scenario:
- AppHost har skapats och startats.
- 
              webfrontend-resursen är tillgänglig och körs.
- En HTTP-begäran kan göras till den webfrontendresursen och returnerar ett lyckat svar (HTTP 200 OK).
Överväg följande testklass:
namespace AspireApp.Tests;
public class IntegrationTest1
{
    [Fact]
    public async Task GetWebResourceRootReturnsOkStatusCode()
    {
        // Arrange
        var builder = await DistributedApplicationTestingBuilder
            .CreateAsync<Projects.AspireApp_AppHost>();
        builder.Services.ConfigureHttpClientDefaults(clientBuilder =>
        {
            clientBuilder.AddStandardResilienceHandler();
        });
        // To capture logs from your tests, see the "Capture logs from tests" section
        // in the documentation or refer to LoggingTest.cs for a complete example
        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);
    }
}
namespace AspireApp.Tests;
[TestClass]
public class IntegrationTest1
{
    [TestMethod]
    public async Task GetWebResourceRootReturnsOkStatusCode()
    {
        // Arrange
        var builder = await DistributedApplicationTestingBuilder
            .CreateAsync<Projects.AspireApp_AppHost>();
        builder.Services.ConfigureHttpClientDefaults(clientBuilder =>
        {
            clientBuilder.AddStandardResilienceHandler();
        });
        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);
    }
}
namespace AspireApp.Tests;
public class IntegrationTest1
{
    [Test]
    public async Task GetWebResourceRootReturnsOkStatusCode()
    {
        // Arrange
        var builder = await DistributedApplicationTestingBuilder
            .CreateAsync<Projects.AspireApp_AppHost>();
        builder.Services.ConfigureHttpClientDefaults(clientBuilder =>
        {
            clientBuilder.AddStandardResilienceHandler();
        });
        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));
    }
}
Föregående kod:
- Förlitar sig på API:et DistributedApplicationTestingBuilder.CreateAsync för att asynkront skapa AppHost.
- 
              appHostär en instans avIDistributedApplicationTestingBuildersom representerar AppHost.
- 
              appHost-instansen har sin tjänstsamling konfigurerad med standardhanteraren för HTTP-motståndskraft. Mer information finns i Skapa motståndskraftiga HTTP-appar: Viktiga utvecklingsmönster.
 
- 
              
- 
              appHosthar anropat sin IDistributedApplicationTestingBuilder.BuildAsync(CancellationToken)-metod, som returnerarDistributedApplication-instansen somapp.- 
              apphar sin tjänstleverantör som hämtar ResourceNotificationService-instansen.
- 
              appstartas asynkront.
 
- 
              
- En HttpClient skapas för den webfrontendresursen genom att anropaapp.CreateHttpClient.
- 
              resourceNotificationServiceanvänds för att vänta tillswebfrontendresurs är tillgänglig och körs.
- En enkel HTTP GET-begäran görs till roten för den webfrontendresursen.
- Testet hävdar att svarsstatuskoden är OK.
Testa resursmiljövariabler
För att ytterligare testa resurser och deras uttryckta beroenden i din Aspire lösning kan du kontrollera att miljövariablerna matas in korrekt. I följande exempel visas hur du testar att den webfrontend resursen har en HTTPS-miljövariabel som matchar den apiservice resursen:
using Aspire.Hosting;
namespace AspireApp.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 envVars = await frontend.Resource.GetEnvironmentVariableValuesAsync(
            DistributedApplicationOperation.Publish);
        // Assert
        Assert.Contains(envVars, static (kvp) =>
        {
            var (key, value) = kvp;
            return key is "services__apiservice__https__0"
                && value is "{apiservice.bindings.https.url}";
        });
    }
}
using Aspire.Hosting;
namespace AspireApp.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 envVars = await frontend.Resource.GetEnvironmentVariableValuesAsync(
            DistributedApplicationOperation.Publish);
        // Assert
        CollectionAssert.Contains(envVars,
            new KeyValuePair<string, string>(
                key: "services__apiservice__https__0",
                value: "{apiservice.bindings.https.url}"));
    }
}
using Aspire.Hosting;
namespace AspireApp.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 envVars = await frontend.Resource.GetEnvironmentVariableValuesAsync(
            DistributedApplicationOperation.Publish);
        // Assert
        Assert.That(envVars, Does.Contain(
            new KeyValuePair<string, string>(
                key: "services__apiservice__https__0",
                value: "{apiservice.bindings.https.url}")));
    }
}
Föregående kod:
- Förlitar sig på API:et DistributedApplicationTestingBuilder.CreateAsync för att asynkront skapa AppHost.
- Den builderinstansen används för att hämta en IResourceWithEnvironment-instans med namnet "webfrontend" från IDistributedApplicationTestingBuilder.Resources.
- Den webfrontendresursen används för att anropa GetEnvironmentVariableValuesAsync för att hämta dess konfigurerade miljövariabler.
- Argumentet DistributedApplicationOperation.Publish skickas när GetEnvironmentVariableValuesAsyncanropas för att ange miljövariabler som publiceras till resursen som bindningsuttryck.
- Med de returnerade miljövariablerna hävdar testet att den webfrontendresursen har en HTTPS-miljövariabel som matchar denapiserviceresursen.
Samla in loggar från tester
När du skriver tester för dina Aspire lösningar kanske du vill samla in och visa loggar för att hjälpa till med felsökning och övervakning av testkörning. 
              DistributedApplicationTestingBuilder Ger åtkomst till tjänstsamlingen så att du kan konfigurera loggning för dina testscenarier.
Konfigurera loggningsleverantörer
Om du vill samla in loggar från dina tester använder du AddLogging metoden på builder.Services för att konfigurera loggningsproviders som är specifika för ditt testramverk:
using Microsoft.Extensions.Logging;
namespace AspireApp.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);
    }
}
using Microsoft.Extensions.Logging;
namespace AspireApp.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);
    }
}
using Microsoft.Extensions.Logging;
namespace AspireApp.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));
    }
}
Konfigurera loggfilter
Eftersom appsettings.json konfigurationen från ditt program inte replikeras automatiskt i testprojekt måste du uttryckligen konfigurera loggfilter. Detta är viktigt för att undvika överdriven loggning från infrastrukturkomponenter som kan överbelasta dina testutdata. Följande kodfragment konfigurerar uttryckligen loggfilter:
builder.Services.AddLogging(logging => logging
    .AddFilter("Default", LogLevel.Information)
    .AddFilter("Microsoft.AspNetCore", LogLevel.Warning)
    .AddFilter("Aspire.Hosting.Dcp", LogLevel.Warning));
Föregående konfiguration:
- Anger standardloggnivån till Informationför de flesta programloggar.
- Minskar bruset från ASP.NET Core infrastrukturen genom att ställa in den på Warningnivå.
- Begränsar Aspire värdinfrastrukturloggar till Warningnivå för att fokusera på programspecifika loggar.
Populära loggningspaket
Olika testramverk har olika paket för loggningsprovider som hjälper dig att hantera loggning under testkörningen:
xUnit.net samlar inte in loggutdata från tester som testutdata. Testerna måste använda ITestOutputHelper gränssnittet för att uppnå detta.
Överväg att använda något av följande loggningspaket för xUnit.net:
- 
              
              📦 MartinCostello.Logging.XUnit – Matar ut ILoggerloggar tillITestOutputHelperutdata.
- 📦 Xunit.DependencyInjection.Logging – Integreras med xUnit.nets beroendeinmatning.
- 📦 Serilog.Extensions.Logging.File – Skriver loggar till filer.
- 📦 Microsoft.Extensions.Logging.Console – matar ut loggar till konsolen.
För MSTest bör du överväga att använda något av följande loggningspaket:
- 📦 Serilog.Extensions.Logging.File – Skriver loggar till filer.
- 📦 Microsoft.Extensions.Logging.Console – matar ut loggar till konsolen.
För NUnit bör du överväga att använda något av följande loggningspaket:
- 📦 Extensions.Logging.NUnit – integreras med NUnit-ramverket.
- 📦 Serilog.Extensions.Logging.File – Skriver loggar till filer.
- 📦 Microsoft.Extensions.Logging.Console – matar ut loggar till konsolen.
Sammanfattning
Den Aspire testprojektmallen gör det enklare att skapa testprojekt för Aspire lösningar. Mallprojektet innehåller ett exempeltest som du kan använda som utgångspunkt för dina tester. 
              DistributedApplicationTestingBuilder följer ett välbekant mönster för WebApplicationFactory<TEntryPoint> i ASP.NET Core. Det gör att du kan skapa en testvärd för ditt distribuerade program och köra tester mot den.
När du använder DistributedApplicationTestingBuilder omdirigeras slutligen alla resursloggar till DistributedApplication som standard. Omdirigeringen av resursloggar möjliggör scenarier där du vill kontrollera att en resurs loggar korrekt.