在 asp.net core/grpc 集成测试中使用 HttpTest

Use HttpTest inside asp.net core/grpc integration test

我有一个 ASP.NET core/gRPC 服务,我想对其进行集成测试。 在 grpc 服务中,我对第 3 方网络 API 进行 Flurl 调用。 我想使用 Flurl 的 HttpTest class 模拟这些调用。 我可以让它以一种非常复杂的方式工作,但它必须更容易。

目前:

            var client = _factory
                    .WithWebHostBuilder(builder =>
                    {
                        builder.ConfigureTestServices(services =>
                        {
                        });
                    })
                .CreateClient(new WebApplicationFactoryClientOptions 
                {BaseAddress = new Uri("http://localhost:5555")});

            using var channel = GrpcChannel.ForAddress("http://localhost:5555",
                new GrpcChannelOptions { HttpClient = client });

            var grpcClient = new MyGrpcService.MyClient(channel);

            var httpTest = new HttpTest();
            var content = new StringContent("some removed json", Encoding.UTF8, "application/json");
            httpTest.RespondWith(content, 200);

...
            var resp = await grpcClient.GetSomeDataAsync(someRequest);

n.b。我正在服务中手动创建我的 IFlurlClient,因为我们需要提供依赖于主机的添加动态证书。

我的主要问题是 Flurl 进行真正的 HTTP 调用而不是使用 HttpTest。

经过一番挖掘,这是由于 HttpTest.Current 的静态性质造成的。 Flurl 使用的静态 HttpTest.Current 是在测试中设置的,但在服务器内部并不存在。我设法通过 FlurlClientFactoryBase 的 DI 覆盖将外部 HttpTest.ResponseQueue 中继到服务内部的一个来破解它的工作,但这似乎远非理想。

是否有规范的方法来集成测试服务并让 Flurl 的 HttpTest 模拟任何传出 HTTP 调用?

为了让 Flurl 在 HttpTest 对象存在期间(有效地向自身发出信号)伪造所有调用,而不求助于静态上下文(这会扰乱并行测试),它需要一些上下文将这些信息从测试中流出,通过你的 SUT,并进入 Flurl 的库位。在 .NET Core 中,执行此操作的机制是 AsyncLocal<T>,这是一个可以流向异步延续的逻辑调用上下文。

然而,默认情况下它无法跨越的一个边界是TestServer。正如 here 所宣布的那样,这是设计使然。虽然我还没有尝试过,但该公告似乎暗示如果您像这样创建测试客户端就可以使它正常工作:

var server = new TestServer(webHostBuilder) 
{
    PreserveExecutionContext = true;
};
var client = server.CreateClient();