Írd meg az első .NET.NET Aspire tesztedet.
Ebből a cikkből megtudhatja, hogyan hozhat létre tesztprojektet, írhat teszteket, és futtathatja őket a .NET.NET Aspire-megoldásokhoz. A cikkben szereplő tesztek nem egységtesztek, hanem funkcionális vagy integrációs tesztek. .NET .NET Aspire számos különböző tesztelési projektsablont, amelyekkel tesztelheti .NET.NET Aspire erőforrásfüggőségeit és kommunikációját. A tesztelési projektsablonok az MSTest, az NUnit és az xUnit tesztelési keretrendszerekhez érhetők el, és tartalmaznak egy mintatesztet, amelyet kiindulópontként használhat a tesztekhez.
A .NET.NET Aspire tesztprojektsablonok a 📦Aspire.Hosting.Testing NuGet-csomagra támaszkodnak. Ez a csomag hozzáférést biztosít a DistributedApplicationTestingBuilder osztályhoz, amely használható tesztgazdagép létrehozására az elosztott alkalmazáshoz. Az elosztott alkalmazástesztelő a DistributedApplication osztályra támaszkodik a alkalmazásgazdalétrehozásához és elindításához.
Tesztprojekt létrehozása
A tesztelési projekt .NET.NET Aspire létrehozásának legegyszerűbb módja a tesztelési projektsablon használata. Ha új .NET.NET Aspire projektet indít, és tesztprojekteket szeretne belefoglalni, a Visual Studio eszközkészlet támogatja ezt a lehetőséget. Ha tesztprojektet ad hozzá egy meglévő .NET.NET Aspire projekthez, a dotnet new
paranccsal létrehozhat egy tesztprojektet:
dotnet new aspire-xunit
dotnet new aspire-mstest
dotnet new aspire-nunit
További információért lásd a .NET parancssori felület dotnet new parancsdokumentációját.
A tesztprojekt megismerése
A következő példatesztelési projekt a .NET.NET Aspire Starter Application sablon részeként lett létrehozva. Ha nem ismeri ezt, tekintse meg a gyorsindítót: az első .NET.NET Aspire projektelkészítése. A .NET.NET Aspire tesztprojekt a célalkalmazás-gazdagépen egy projekthivatkozás-függőséget vesz igénybe. Fontolja meg a sablonprojektet:
<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.4" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
<PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.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="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.8.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>
<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.6.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>
Az előző projektfájl meglehetősen szabványos. Van egy PackageReference
a 📦Aspire.Hosting.Testing NuGet-csomag, amely tartalmazza a tesztek írásához szükséges típusokat .NET.NET Aspire projektekhez.
A sablontesztelési projekt egyetlen teszttel rendelkező IntegrationTest1
osztályt tartalmaz. A teszt a következő forgatókönyvet ellenőrzi:
- Az alkalmazás gazdagépének létrehozása és elindítása sikeresen megtörtént.
- Az
webfrontend
erőforrás elérhető és fut. - HTTP-kérést lehet küldeni az
webfrontend
erőforrásnak, és sikeres választ ad vissza (HTTP 200 OK).
Vegye figyelembe a következő tesztosztályt:
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));
}
}
Az előző kód:
- A DistributedApplicationTestingBuilder.CreateAsync API használatával aszinkron módon hozza létre az alkalmazás környezetet.
- A
appHost
az alkalmazás gazdagépét képviselőIDistributedApplicationTestingBuilder
egy példánya. - A
appHost
példány szolgáltatásgyűjteménye a szabványos HTTP-rugalmasságkezelővel van konfigurálva. További információ: Rugalmas HTTP-alkalmazások létrehozása: Kulcsfejlesztési minták.
- A
- A
appHost
meghívja saját IDistributedApplicationTestingBuilder.BuildAsync(CancellationToken) metódusát, amely visszaadja aDistributedApplication
példányt mintapp
.- A
app
szolgáltatója lekéri a(z) ResourceNotificationService-példányt. - A
app
aszinkron módon indul el.
- A
- A HttpClient erőforráshoz
webfrontend
jön létre aapp.CreateHttpClient
meghívásával. - A
resourceNotificationService
arra szolgál, hogy megvárja, amíg awebfrontend
erőforrás elérhető és fut. - A
webfrontend
erőforrás gyökeréhez egyszerű HTTP GET-kérést küldünk. - A teszt azt állítja, hogy a válasz állapotkódja
OK
.
Erőforrás-környezeti változók tesztelése
Az erőforrások és azok kifejezett függőségeinek a .NET.NET Aspire megoldásban való további teszteléséhez állíthatja, hogy a környezeti változók megfelelően vannak injektálva. Az alábbi példa bemutatja, hogyan tesztelhetjük az webfrontend
erőforrás HTTPS környezeti változóját, amely az apiservice
erőforrásra oldódik fel:
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}")));
}
}
Az előző kód:
- A DistributedApplicationTestingBuilder.CreateAsync API használatával aszinkron módon hozza létre az alkalmazás környezetet.
- A
builder
példány arra szolgál, hogy egy "webfrontend" nevű IResourceWithEnvironment példányt le lehessen kérni a IDistributedApplicationTestingBuilder.Resources-ből. - A(z)
webfrontend
erőforrást arra használják, hogy felhívják GetEnvironmentVariableValuesAsync-et, és lekérjék annak konfigurált környezeti változóit. - A DistributedApplicationOperation.Publish argumentum akkor lesz átadva, amikor meghívja
GetEnvironmentVariableValuesAsync
az erőforrásban kötési kifejezésként közzétett környezeti változók megadásához. - A visszaadott környezeti változókkal a teszt azt állítja, hogy az
webfrontend
erőforrás rendelkezik egy HTTPS környezeti változóval, amely aapiservice
erőforrásra hivatkozik.
Összefoglalás
A .NET Aspire tesztelési projektsablon megkönnyíti a tesztprojektek létrehozását .NET Aspire megoldásokhoz. A sablonprojekt tartalmaz egy mintatesztet, amelyet kiindulópontként használhat a tesztekhez. A DistributedApplicationTestingBuilder
egy ismerős mintát követ, mint a WebApplicationFactory<TEntryPoint> a ASP.NET Core-ben. Lehetővé teszi egy tesztgazda létrehozását az elosztott alkalmazáshoz, és teszteket futtathat rajta.
Végül, amikor a DistributedApplicationTestingBuilder
-t használják, alapértelmezés szerint az összes erőforrásnaplót átirányítják a DistributedApplication
-re. Az erőforrásnaplók átirányítása olyan forgatókönyveket tesz lehetővé, amelyekben az erőforrás helyes naplózását szeretné érvényesíteni.