正常情况下,中间件会在主程序入口统一进行实例化,这样如果想单独测试某一个中间件就很不方便,为了能测试单个中间件,可以使用 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 ,测试没通过,证明自定义中间件是没问题的。