I have an ASP.NET Core middleware which is responsible for adding headers to a response. In following best practices, I am executing the header changes in the context of HttpResponse.OnStarting(Func<Task>)
, which ensures callback execution immediately before the response is flushed to the client.
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);
}
}
This works as-intended, but I am not sure how best to write a unit test for this middleware which actually fires HttpResponse.OnStarting()
. The only thing I could come up with was using a Microsoft.AspNetCore.TestHost
to build a TestServer
which integrates the middleware and executes the full request pipeline. While functional, this is more an integration test, than a true unit test.
[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();
});
}
}
Is there a way to trigger HttpResponse.OnStarting()
on the HttpContext passed to my middleware, without an end-to-end integration test?
DefaultHttpContext
,DefaultHttpResponse
andHttpResponseFeature
, I have yet to determine how the callback passed toHttpResponse.OnStarting()
gets invoked. github.com/aspnet/HttpAbstractions/blob/dev/src/… github.com/aspnet/HttpAbstractions/blob/dev/src/… github.com/aspnet/HttpAbstractions/blob/dev/src/… – Grice