dotnet / aspire

Tools, templates, and packages to accelerate building observable, production-ready apps
https://learn.microsoft.com/dotnet/aspire
MIT License
3.84k stars 462 forks source link

Hello, Integration testing problem, hoping to get technical support. #4274

Closed bit365 closed 5 months ago

bit365 commented 5 months ago

In the integration test, DistributedApplicationTestingBuilder was used to create a test environment. As a result, the service discovery could not be automatically injected. The debugging found that the HTTP endpoint of the service was not injected into the application's microservices through environment variables.

Test

[Fact]
public async Task ProductServiceGetProductReturnsProductDetails()
{
    // Arrange
    IDistributedApplicationTestingBuilder appHost = await DistributedApplicationTestingBuilder.CreateAsync<Projects.HelloWorld_AppHost>();

    await using DistributedApplication app = await appHost.BuildAsync();
    await app.StartAsync();

    // Act
    HttpClient identityServiceHttpClient = app.CreateHttpClient("identityservice");
    HttpResponseMessage loginResponse = await identityServiceHttpClient.PostAsJsonAsync("api/Account/Login", new
    {
        UserName = "admin",
        Password = "admin"
    });

    AccessTokenResponse? accessTokenResponse = await loginResponse.Content.ReadFromJsonAsync<AccessTokenResponse>();

    HttpClient productServiceHttpClient = app.CreateHttpClient("productservice");
    productServiceHttpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessTokenResponse?.AccessToken);

    HttpResponseMessage productDetailsResponse = await productServiceHttpClient.GetAsync("api/Products/1");

    JsonNode? result = await productDetailsResponse.Content.ReadFromJsonAsync<JsonNode>();

    string? productName = result?["Name"]?.GetValue<string>();

    // Assert
    Assert.NotNull(productName);
    Assert.Equal("Product 1", productName);
}

Host

var builder = DistributedApplication.CreateBuilder(args);

var identityService = builder.AddProject<Projects.HelloWorld_IdentityService>("identityservice");

var productService = builder.AddProject<Projects.HelloWorld_ProductService>("productservice")
    .WithReference(identityService);

builder.Build().Run();

Problems

Because the productService. WithReference (identityService), it can be found in the productService service through httpclient.GetAsync ("http://IdentityService") It can work normally.

However, in the integrated test environment, use the DistributedApplicationTestingBuilder to start. productService cannot find the identityService service found. Debug found that the HTTP end -point environment variables of the service discovered were not automatically configured in the productService, so the test could not be performed.

Integrated testing may require Unicom test, and service1->service2-> service3 is performed throughout the link test.

ReubenBond commented 5 months ago

Hi @bit365, could you please elaborate on what isn't working? When you debug the tests, what do you see? The env vars for service discovery ought to be getting injected. Does your app work when you run it outside of the testing scenario? Which version of Visual Studio are you using?

bit365 commented 5 months ago

The problem is simple, all services started through a normal Host can call each other through service discovery.

For services started through the test environment, the service cannot be discovered in the microservice, prompting that the host is not found because the endpoint environment variable associated with the service name is not found.

ReubenBond commented 5 months ago

@bit365 it is not clear what the issue is yet. My hunch is that it could be related to launch profiles. Could you show the launchSettings.json files for your projects?

bit365 commented 5 months ago

host code:

service1.WithReference(service2)

server2 code:

httpClient.GetAsync("https://service1")

Running the HOST project directly is able to serve discovery and work properly, and server1 is resolved to the endpoint.

If you use DistributedApplicationTestingBuilder to start a test environment and perform integration tests on service2, httpClient.GetAsync("https://service1") fails to work, prompting an unknown service1 host and invalidating service discovery.