첫 번째 .NET.NET Aspire 테스트 작성
이 문서에서는 테스트 프로젝트를 만들고, 테스트를 작성하고, .NET.NET Aspire 솔루션에 대해 실행하는 방법을 알아봅니다. 이 문서의 테스트는 단위 테스트가 아니라 기능 또는 통합 테스트입니다. .NET .NET Aspire .NET .NET Aspire 리소스 종속성 및 해당 통신을 테스트하는 데 사용할 수 있는 테스트 프로젝트 템플릿 여러 변형이 포함되어 있습니다. 테스트 프로젝트 템플릿은 MSTest, NUnit 및 xUnit 테스트 프레임워크에 사용할 수 있으며 테스트의 시작점으로 사용할 수 있는 샘플 테스트를 포함합니다.
.NET .NET Aspire 테스트 프로젝트 템플릿은 📦Aspire.Hosting.Testing NuGet 패키지에 의존합니다. 이 패키지는 분산 애플리케이션에 대한 테스트 호스트를 만드는 데 사용되는 DistributedApplicationTestingBuilder 클래스를 노출합니다. 분산 애플리케이션 테스트 빌더는 DistributedApplication 클래스를 사용하여 앱 호스트만들고 시작합니다.
테스트 프로젝트 만들기
.NET
.NET Aspire 테스트 프로젝트를 만드는 가장 쉬운 방법은 테스트 프로젝트 템플릿을 사용하는 것입니다. 새 .NET.NET Aspire 프로젝트를 시작하고 테스트 프로젝트를 포함하려는 경우 Visual Studio 도구에서 해당 옵션지원합니다. 기존 .NET.NET Aspire 프로젝트에 테스트 프로젝트를 추가하는 경우 dotnet new
명령을 사용하여 테스트 프로젝트를 만들 수 있습니다.
dotnet new aspire-xunit
dotnet new aspire-mstest
dotnet new aspire-nunit
자세한 내용은 .NET CLI dotnet new 명령 설명서를 참조하세요.
테스트 프로젝트 탐색
다음 예제 테스트 프로젝트는 .NET.NET Aspire Starter 애플리케이션 템플릿의 일부로 만들어졌습니다. 익숙하지 않다면 빠른 시작: 첫 번째 .NET.NET Aspire 프로젝트빌드를 참고하세요. .NET .NET Aspire 테스트 프로젝트는 대상 앱 호스트에 대한 프로젝트 참조 종속성을 사용합니다. 템플릿 프로젝트를 고려합니다.
<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.2" />
<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.1" />
<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>
위의 프로젝트 파일은 상당히 표준입니다.
PackageReference
에는 📦Aspire대한 Hosting.Testing NuGet 패키지가 있으며, 이 패키지는 .NET.NET Aspire 프로젝트에 대한 테스트를 작성하는 데 필요한 형식을 포함하고 있습니다.
템플릿 테스트 프로젝트에는 단일 테스트가 있는 IntegrationTest1
클래스가 포함됩니다. 테스트는 다음 시나리오를 확인합니다.
- 앱 호스트가 성공적으로 만들어지고 시작됩니다.
-
webfrontend
리소스를 사용할 수 있고 실행 중입니다. -
webfrontend
리소스에 대한 HTTP 요청을 수행하고 성공적인 응답(HTTP 200 OK)을 반환할 수 있습니다.
다음 테스트 클래스를 고려합니다.
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));
}
}
앞의 코드는 다음과 같습니다.
-
DistributedApplicationTestingBuilder.CreateAsync API를 사용하여 앱 호스트를 비동기적으로 만듭니다.
-
appHost
앱 호스트를 나타내는IDistributedApplicationTestingBuilder
인스턴스입니다. -
appHost
인스턴스에는 표준 HTTP 복원력 처리기로 구성된 서비스 컬렉션이 있습니다. 자세한 내용은 복원력 있는 HTTP 앱 빌드 :주요 개발 패턴을 참조하세요.
-
-
appHost
의 IDistributedApplicationTestingBuilder.BuildAsync(CancellationToken) 메서드가 호출되며,DistributedApplication
로서app
인스턴스를 반환합니다.-
app
서비스 공급자가 ResourceNotificationService 인스턴스를 가져옵니다. -
app
비동기적으로 시작됩니다.
-
-
HttpClient를 호출하여
webfrontend
리소스를 위한app.CreateHttpClient
가 생성됩니다. -
resourceNotificationService
는webfrontend
리소스를 사용할 수 있고 실행될 준비가 될 때까지 기다리는 데 사용됩니다. -
webfrontend
리소스의 루트에 대한 간단한 HTTP GET 요청이 이루어집니다. - 테스트는 응답 상태 코드가
OK
인지 확인합니다.
리소스 환경 변수 테스트
.NET
.NET Aspire 솔루션에서 리소스 및 해당 표현된 종속성을 추가로 테스트하려면 환경 변수가 올바르게 삽입되도록 어설션할 수 있습니다. 다음 예제에서는 webfrontend
리소스에 apiservice
리소스로 확인되는 HTTPS 환경 변수가 있는지 테스트하는 방법을 보여 줍니다.
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}")));
}
}
앞의 코드는 다음과 같습니다.
- DistributedApplicationTestingBuilder.CreateAsync API를 사용하여 앱 호스트를 비동기적으로 만듭니다.
-
builder
인스턴스는 "webfrontend"라는 이름의 IResourceWithEnvironment 인스턴스를 IDistributedApplicationTestingBuilder.Resources에서 가져오는 데 사용됩니다. -
webfrontend
리소스는 구성된 환경 변수를 검색하기 위해 GetEnvironmentVariableValuesAsync 호출하는 데 사용됩니다. -
DistributedApplicationOperation.Publish 인수는
GetEnvironmentVariableValuesAsync
호출하여 리소스에 바인딩 식으로 게시되는 환경 변수를 지정할 때 전달됩니다. - 반환된 환경 변수를 사용하여, 테스트는
webfrontend
리소스에apiservice
리소스로 연결된 HTTPS 환경 변수가 있음을 확인합니다.
요약
.NET Aspire 테스트 프로젝트 템플릿을 사용하면 .NET Aspire 솔루션에 대한 테스트 프로젝트를 더 쉽게 만들 수 있습니다. 템플릿 프로젝트에는 테스트의 시작점으로 사용할 수 있는 샘플 테스트가 포함되어 있습니다.
DistributedApplicationTestingBuilder
는 WebApplicationFactory<TEntryPoint>에서 ASP.NET Core의 익숙한 패턴을 따릅니다. 이를 통해 분산 애플리케이션에 대한 테스트 호스트를 만들고 이에 대한 테스트를 실행할 수 있습니다.
마지막으로 DistributedApplicationTestingBuilder
사용하는 경우 모든 리소스 로그는 기본적으로 DistributedApplication
리디렉션됩니다. 리소스 로그의 리디렉션을 사용하면 리소스가 올바르게 로깅되고 있음을 어설션하려는 시나리오를 사용할 수 있습니다.
참고 항목
- xUnit 및 dotnet test를 사용하여 .NET에서 C#으로 단위 테스트
- MSTest 개요
- NUnit과
Core를 사용하여 C#의 단위 테스트
.NET Aspire