正常情况下,中间件会在主程序入口统一进行实例化,这样如果想单独测试某一个中间件就很不方便,为了能测试单个中间件,可以使用 TestServer 单独测试。 这样便可以:
- 实例化只包含需要测试的组件的应用管道。
- 发送自定义请求以验证中间件行为。
这样测试的优点:
- 请求会发送到内存中,而不是通过网络进行序列化。
- 这样可以避免产生额外的问题,例如端口管理和 HTTPS 证书。
- 中间件中的异常可以直接流回调用测试。
- 可以直接在测试中自定义服务器数据结构,如 HttpContext。
设置 TestServer
在测试项目中,创建测试:
-
生成并启动使用 TestServer 的主机。
-
添加中间件使用的任何所需服务。
-
为 Microsoft.AspNetCore.TestHost NuGet 包添加对项目的包引用。
-
将处理管道配置为使用中间件进行测试。
我这写了一个简单的测试代码:
测试类:
public class UnitTest1
{
[Fact]
public async Task MiddlewareTest()
{
using var host = await new HostBuilder()
.ConfigureWebHost(webBuilder =>
{
webBuilder
.UseTestServer()
.ConfigureServices(services =>
{
services.AddRouting();
})
.Configure(app =>
{
app.UseRouting();
app.UseMiddleware<MyMiddleware>();
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/hello", () =>
"Hello Tests");
});
});
})
.StartAsync();
var client = host.GetTestClient();
var response = await client.GetAsync("/hello");
Assert.True(response.IsSuccessStatusCode);
var responseBody = await response.Content.ReadAsStringAsync();
Assert.Equal("Hello Tests", responseBody);
}
}
自定义的 MyMiddleware 代码如下:
public class MyMiddleware
{
private readonly RequestDelegate _next;//请求委托:用于生成请求管道
public MyMiddleware(ILogger<MyMiddleware> logger, RequestDelegate next)
{
_next = next;
}
public Task InvokeAsync(HttpContext context)
{
//context.Response.StatusCode = (int)HttpStatusCode.Found;
// 调用下一个中间件
return _next(context);
}
}
运行测试:
测试通过:
接下来我们通过MyMiddleware自定义中间件设置一下响应状态 StatusCode 为302:
再次调试测试一下:
可以看到 StatusCode: 302 ,测试没通过,证明自定义中间件是没问题的。