gpt4 book ai didi

c# - 单元测试 ASP.NET Core HttpResponse.OnStarting()

转载 作者:行者123 更新时间:2023-12-01 19:12:54 25 4
gpt4 key购买 nike

我有一个 ASP.NET Core 中间件,它负责向响应添加 header 。在以下最佳实践中,我在 HttpResponse.OnStarting(Func<Task>) 的上下文中执行 header 更改,这确保回调在响应刷新到客户端之前立即执行。

public class ResponseHeadersMiddleware
{
private readonly RequestDelegate _next;

public ResponseHeadersMiddleware(RequestDelegate next)
{
_next = next;
}

public async Task Invoke(HttpContext context)
{
context.Response.OnStarting(() =>
{
context.Response.Headers.Add("X-Some-Header", "Foobar");

return Task.CompletedTask;
});

// Pass the request through the pipeline
await _next(context);
}
}

这按预期工作,但我不确定如何最好地为这个实际触发的中间件编写单元测试 HttpResponse.OnStarting() 。我唯一能想到的就是使用 Microsoft.AspNetCore.TestHost建立一个TestServer它集成了中间件并执行完整的请求管道。虽然功能齐全,但这更多的是集成测试,而不是真正的单元测试。

[Fact]
public async Task when_adding_response_headers()
{
// ARRANGE
var subject = new TestServer(new WebHostBuilder()
.UseStartup<TestStartup<ResponseHeadersMiddleware>>());

// ACT
var response = await subject.CreateClient()
.SendAsync(new HttpRequestMessage(HttpMethod.Get, "/")); // middleware fires for all requests

// ASSERT
Assert.True(response.Headers.TryGetValues("X-Some-Header", out var someHeader));
Assert.Equals("Foobar", someHeader.FirstOrDefault()
}

private class TestStartup<TMiddleware> where TMiddleware : class
{
public void ConfigureServices(IServiceCollection services)
{
RequestDelegate requestDelegate = context => Task.FromResult(0);

services.AddSingleton(requestDelegate);
services.AddSingleton<TMiddleware>();
}

public void Configure(IApplicationBuilder app)
{
dynamic middleware = app.ApplicationServices.GetService(typeof(TMiddleware));

app.Use(async (ctx, next) =>
{
await middleware.Invoke(ctx);
await next();
});
}
}

有没有办法触发HttpResponse.OnStarting()在传递给我的中间件的 HttpContext 上,没有端到端集成测试?

最佳答案

在对存储库进行了一些挖掘并查看了他们的一些测试之后,我想出了这个想法来利用受控上下文的响应功能。

这意味着找到一种方法来捕获传递给 OnStarting 的回调。决定尝试通过虚拟响应功能来获取它。

private class DummyResponseFeature : IHttpResponseFeature {
public Stream Body { get; set; }

public bool HasStarted { get { return hasStarted; } }

public IHeaderDictionary Headers { get; set; } = new HeaderDictionary();

public string ReasonPhrase { get; set; }

public int StatusCode { get; set; }

public void OnCompleted(Func<object, Task> callback, object state) {
//...No-op
}

public void OnStarting(Func<object, Task> callback, object state) {
this.callback = callback;
this.state = state;
}

bool hasStarted = false;
Func<object, Task> callback;
object state;

public Task InvokeCallBack() {
hasStarted = true;
return callback(state);
}
}

在测试中,我将在 HttpContext 上设置该功能,然后直接测试中间件。

[Fact]
public async Task when_adding_response_headers() {
// ARRANGE
var feature = new DummyResponseFeature();
var context = new DefaultHttpContext();
context.Features.Set<IHttpResponseFeature>(feature);

RequestDelegate next = async (ctx) => {
await feature.InvokeCallBack();
};

var subject = new ResponseHeadersMiddleware(next);

// ACT
await subject.Invoke(context);

// ASSERT
var response = context.Response;
Assert.True(response.Headers.TryGetValues("X-Some-Header", out var someHeader));
Assert.Equals("Foobar", someHeader.FirstOrDefault()
}

当中间件中等待请求委托(delegate)时,让请求委托(delegate)调用捕获回调

关于c# - 单元测试 ASP.NET Core HttpResponse.OnStarting(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49740194/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com