如何让C# TestServer主动抛出异常以测试ErrorHandlingMiddleware
如何在TestServer中触发异常以测试ErrorHandlingMiddleware?
要测试中间件的异常捕获逻辑,你可以通过以下两种方式主动触发异常:
方法1:添加会抛出异常的测试端点(集成测试)
在TestServer的配置中新增一个专门抛出异常的测试路由,请求该路由时,后续的next委托会执行异常代码,被中间件的catch块捕获。
修改你的GetHost方法,在Configure中添加测试端点:
private async Task<IHost> GetHost() { return await new HostBuilder() .ConfigureWebHost(webBuilder => { webBuilder .UseTestServer() .ConfigureServices(services => { services.Add(ServiceDescriptor.Scoped<IErrorHandlingService, ErrorHandlingService>()); }) .Configure(app => { app.UseMiddleware<ErrorHandlingMiddleware>(); // 添加抛出异常的测试端点 app.MapGet("/test-throw-exception", () => { throw new InvalidOperationException("测试异常:来自端点的错误"); }); }); }) .StartAsync(); }
编写测试方法验证异常处理逻辑:
[Fact] public async Task ExceptionThrown_ShouldBeHandledByMiddleware() { // Arrange using var host = await GetHost(); var server = host.GetTestServer(); server.BaseAddress = new Uri("https://example.com/"); // Act var response = await server.CreateRequest("/test-throw-exception") .GetAsync(); // Assert // 验证响应状态码 response.StatusCode.Should().Be((int)HttpStatusCode.InternalServerError); // 验证错误响应内容 var errorResponse = await response.Content.ReadFromJsonAsync<ErrorResponse>(); errorResponse.ErrorContent.ErrorMessage.Should().Contain("测试异常:来自端点的错误"); errorResponse.ErrorContent.HttpCode.Should().Be(HttpStatusCode.InternalServerError); // 验证ErrorHandlingService的错误记录 var errHandler = host.Services.GetRequiredService<IErrorHandlingService>(); errHandler.ErrorResponse.ErrorContent.TraceID.Should().NotBeEmpty(); }
方法2:直接模拟抛出异常的RequestDelegate(单元测试)
如果想更聚焦中间件本身的逻辑,无需完整TestServer,可以直接构造中间件实例,传入会抛出异常的RequestDelegate,同时模拟依赖的IErrorHandlingService和IHostEnvironment。
示例代码(使用Moq框架):
[Fact] public async Task Invoke_WhenNextThrowsException_HandlesErrorCorrectly() { // Arrange // 模拟ErrorHandlingService var mockErrHandler = new Mock<IErrorHandlingService>(); mockErrHandler.Setup(h => h.ErrorResponse).Returns(new ErrorResponse { ErrorContent = new ErrorContent(), StatusCode = HttpStatusCode.InternalServerError }); // 模拟HostEnvironment(非生产环境) var mockEnv = new Mock<IHostEnvironment>(); mockEnv.Setup(e => e.IsProduction()).Returns(false); // 定义会抛出异常的next委托 var testException = new InvalidOperationException("测试异常:来自next委托"); RequestDelegate next = _ => throw testException; // 构造中间件 var middleware = new ErrorHandlingMiddleware(next, mockErrHandler.Object); var context = new DefaultHttpContext(); // Act await middleware.Invoke(context, mockEnv.Object); // Assert // 验证响应状态码 context.Response.StatusCode.Should().Be((int)HttpStatusCode.InternalServerError); // 验证ErrorHandlingService是否正确记录了错误 mockErrHandler.Verify(h => h.AddError(It.Is<MyError>(err => err.ErrorMessage.Contains(testException.ToString()) && err.HttpCode == HttpStatusCode.InternalServerError && err.Title == "An unknown error occurred during execution" )), Times.Once); }
两种方法的区别
- 方法1是集成测试,模拟真实HTTP请求流程,能验证中间件在完整管道中的表现;
- 方法2是单元测试,直接测试中间件核心逻辑,运行更快,更易隔离问题。
内容的提问来源于stack exchange,提问作者penny
相关产品推荐
相关产品推荐

