Uw eerste .NET.NET Aspire test schrijven
In dit artikel leert u hoe u een testproject maakt, tests schrijft en uitvoert voor uw .NET.NET Aspire-oplossingen. De tests in dit artikel zijn geen eenheidstests, maar eerder functionele of integratietests. .NET .NET Aspire bevat verschillende variaties van projectsjablonen die u kunt gebruiken om uw .NET.NET Aspire resourceafhankelijkheden en hun communicatie te testen. De testprojectsjablonen zijn beschikbaar voor MSTest-, NUnit- en xUnit-testframeworks en bevatten een voorbeeldtest die u als uitgangspunt voor uw tests kunt gebruiken.
De .NET.NET Aspire testprojectsjablonen zijn afhankelijk van de 📦Aspire. Hosting.Testing NuGet-pakket. Met dit pakket wordt de DistributedApplicationTestingBuilder-klasse weergegeven, die wordt gebruikt om een testhost te maken voor uw gedistribueerde toepassing. De bouwer voor gedistribueerde toepassingstests is afhankelijk van de DistributedApplication-klasse om de host-app te maken ente starten.
Een testproject maken
De eenvoudigste manier om een .NET.NET Aspire testproject te maken, is door de sjabloon voor het testproject te gebruiken. Als u een nieuw .NET.NET Aspire project start en testprojecten wilt opnemen, ondersteunt de Visual Studio hulpprogramma's die optie. Als u een testproject toevoegt aan een bestaand .NET.NET Aspire-project, kunt u de opdracht dotnet new
gebruiken om een testproject te maken:
dotnet new aspire-xunit
dotnet new aspire-mstest
dotnet new aspire-nunit
Raadpleeg de documentatie voor de opdracht 'dotnet new' van
Het testproject verkennen
Het volgende voorbeeldtestproject is gemaakt als onderdeel van de .NET.NET Aspire Starter Application-sjabloon. Als u er niet bekend mee bent, raadpleegt u Quickstart: Uw eerste .NET.NET Aspire project bouwen. Het .NET.NET Aspire-testproject heeft een projectreferentieafhankelijkheid van de doel-app-host. Houd rekening met het sjabloonproject:
<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.0.0" />
<PackageReference Include="coverlet.collector" Version="6.0.3" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
<PackageReference Include="xunit" Version="2.9.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.0.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="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.0.0" />
<PackageReference Include="MSTest" Version="3.7.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="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.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
<PackageReference Include="NUnit" Version="4.3.2" />
<PackageReference Include="NUnit.Analyzers" Version="4.5.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>
Het voorgaande projectbestand is redelijk standaard. Er is een PackageReference
aan de 📦Aspire. Hosting.Testing NuGet-pakket, dat de vereiste typen bevat voor het schrijven van tests voor .NET.NET Aspire projecten.
Het sjabloontestproject bevat een IntegrationTest1
klasse met één test. De test controleert het volgende scenario:
- De app host is succesvol gemaakt en gestart.
- De
webfrontend
bron is beschikbaar en actief. - Een HTTP-aanvraag kan worden ingediend bij de
webfrontend
resource en retourneert een geslaagd antwoord (HTTP 200 OK).
Houd rekening met de volgende testklasse:
namespace AspireApp.Tests;
public class IntegrationTest1
{
[Fact]
public async Task GetWebResourceRootReturnsOkStatusCode()
{
// Arrange
var appHost = await DistributedApplicationTestingBuilder
.CreateAsync<Projects.AspireApp_AppHost>();
appHost.Services.ConfigureHttpClientDefaults(clientBuilder =>
{
clientBuilder.AddStandardResilienceHandler();
});
// To output logs to the xUnit.net ITestOutputHelper,
// consider adding a package from https://www.nuget.org/packages?q=xunit+logging
await using var app = await appHost.BuildAsync();
var resourceNotificationService = app.Services
.GetRequiredService<ResourceNotificationService>();
await app.StartAsync();
// Act
var httpClient = app.CreateHttpClient("webfrontend");
await resourceNotificationService.WaitForResourceAsync(
"webfrontend",
KnownResourceStates.Running
)
.WaitAsync(TimeSpan.FromSeconds(30));
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 appHost = await DistributedApplicationTestingBuilder
.CreateAsync<Projects.AspireApp_AppHost>();
appHost.Services.ConfigureHttpClientDefaults(clientBuilder =>
{
clientBuilder.AddStandardResilienceHandler();
});
await using var app = await appHost.BuildAsync();
var resourceNotificationService = app.Services
.GetRequiredService<ResourceNotificationService>();
await app.StartAsync();
// Act
var httpClient = app.CreateHttpClient("webfrontend");
await resourceNotificationService.WaitForResourceAsync(
"webfrontend",
KnownResourceStates.Running
)
.WaitAsync(TimeSpan.FromSeconds(30));
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 appHost = await DistributedApplicationTestingBuilder
.CreateAsync<Projects.AspireApp_AppHost>();
appHost.Services.ConfigureHttpClientDefaults(clientBuilder =>
{
clientBuilder.AddStandardResilienceHandler();
});
await using var app = await appHost.BuildAsync();
var resourceNotificationService = app.Services
.GetRequiredService<ResourceNotificationService>();
await app.StartAsync();
// Act
var httpClient = app.CreateHttpClient("webfrontend");
await resourceNotificationService.WaitForResourceAsync(
"webfrontend",
KnownResourceStates.Running
)
.WaitAsync(TimeSpan.FromSeconds(30));
var response = await httpClient.GetAsync("/");
// Assert
Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK));
}
}
De voorgaande code:
- Is afhankelijk van de DistributedApplicationTestingBuilder.CreateAsync-API om de app-host asynchroon te maken.
- De
appHost
is een exemplaar vanIDistributedApplicationTestingBuilder
dat de app-host vertegenwoordigt. - Het
appHost
exemplaar heeft de dienstencollectie ingericht met de standaard HTTP-resilience handler. Zie Tolerante HTTP-apps bouwen: Belangrijke ontwikkelingspatronenvoor meer informatie.
- De
- De
appHost
heeft de IDistributedApplicationTestingBuilder.BuildAsync(CancellationToken) methode aangeroepen, waarmee hetDistributedApplication
exemplaar wordt geretourneerd als deapp
.- De
app
laat de serviceprovider de ResourceNotificationService instantie verkrijgen. -
app
wordt asynchroon gestart.
- De
- Er wordt een HttpClient gemaakt voor de
webfrontend
bron doorapp.CreateHttpClient
aan te roepen. - De
resourceNotificationService
wordt gebruikt om te wachten tot dewebfrontend
resource beschikbaar is en actief is. - Er wordt een eenvoudige HTTP GET-aanvraag gedaan naar de root van de
webfrontend
-resource. - De test bevestigt dat de antwoordstatuscode
OK
is.
Resourceomgevingsvariabelen testen
Als u resources en hun uitgedrukte afhankelijkheden in uw .NET.NET Aspire oplossing verder wilt testen, kunt u bevestigen dat omgevingsvariabelen correct worden geïnjecteerd. In het volgende voorbeeld ziet u hoe u kunt testen of de webfrontend
-resource een HTTPS-omgevingsvariabele heeft die wordt omgezet in de apiservice
-resource:
using Aspire.Hosting;
namespace AspireApp.Tests;
public class EnvVarTests
{
[Fact]
public async Task WebResourceEnvVarsResolveToApiService()
{
// Arrange
var appHost = await DistributedApplicationTestingBuilder
.CreateAsync<Projects.AspireApp_AppHost>();
var frontend = (IResourceWithEnvironment)appHost.Resources
.Single(static r => r.Name == "webfrontend");
// Act
var envVars = await frontend.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 appHost = await DistributedApplicationTestingBuilder
.CreateAsync<Projects.AspireApp_AppHost>();
var frontend = (IResourceWithEnvironment)appHost.Resources
.Single(static r => r.Name == "webfrontend");
// Act
var envVars = await frontend.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 appHost = await DistributedApplicationTestingBuilder
.CreateAsync<Projects.AspireApp_AppHost>();
var frontend = (IResourceWithEnvironment)appHost.Resources
.Single(static r => r.Name == "webfrontend");
// Act
var envVars = await frontend.GetEnvironmentVariableValuesAsync(
DistributedApplicationOperation.Publish);
// Assert
Assert.That(envVars, Does.Contain(
new KeyValuePair<string, string>(
key: "services__apiservice__https__0",
value: "{apiservice.bindings.https.url}")));
}
}
De voorgaande code:
- Is afhankelijk van de DistributedApplicationTestingBuilder.CreateAsync-API om de app-host asynchroon te maken.
- Het
builder
exemplaar wordt gebruikt om een IResourceWithEnvironment exemplaar met de naam 'webfrontend' op te halen uit de IDistributedApplicationTestingBuilder.Resources. - De
webfrontend
resource wordt gebruikt om GetEnvironmentVariableValuesAsync aan te roepen om de geconfigureerde omgevingsvariabelen op te halen. - Het argument DistributedApplicationOperation.Publish wordt doorgegeven bij het aanroepen van
GetEnvironmentVariableValuesAsync
om omgevingsvariabelen op te geven die als bindingexpressies naar de resource worden gepubliceerd. - Met de geretourneerde omgevingsvariabelen bevestigt de test dat de
webfrontend
-resource een HTTPS-omgevingsvariabele heeft die wordt omgezet in deapiservice
-resource.
Samenvatting
Met de .NET Aspire testprojectsjabloon kunt u eenvoudiger testprojecten maken voor .NET Aspire oplossingen. Het sjabloonproject bevat een voorbeeldtest die u als uitgangspunt voor uw tests kunt gebruiken. De DistributedApplicationTestingBuilder
volgt een bekend patroon voor de WebApplicationFactory<TEntryPoint> in ASP.NET Core. Hiermee kunt u een testhost voor uw gedistribueerde toepassing maken en tests uitvoeren.
Ten slotte worden bij het gebruik van de DistributedApplicationTestingBuilder
alle resourcelogboeken standaard omgeleid naar de DistributedApplication
. Het omleiden van resourcelogboeken maakt scenario's mogelijk waarin u wilt bevestigen dat een resource correct wordt gelogd.