【问题标题】:Configure AspNetCore TestServer to return 500 instead of throwing exception配置 AspNetCore TestServer 返回 500 而不是抛出异常
【发布时间】:2018-11-28 07:40:57
【问题描述】:

我正在开发一个 Web API,在某些情况下会以 500 响应(我知道设计很丑,但对此无能为力)。在测试中有一个包含 AspNetCore.TestHost 的 ApiFixture:

public class ApiFixture
{
    public TestServer ApiServer { get; }
    public HttpClient HttpClient { get; }

    public ApiFixture()
    {
        var config = new ConfigurationBuilder()
            .AddEnvironmentVariables()
            .Build();

        var path = Assembly.GetAssembly(typeof(ApiFixture)).Location;
        var hostBuilder = new WebHostBuilder()
            .UseContentRoot(Path.GetDirectoryName(path))
            .UseConfiguration(config)
            .UseStartup<Startup>();

        ApiServer = new TestServer(hostBuilder);
        HttpClient = ApiServer.CreateClient();
    }
}

当我从这个夹具使用 HttpClient 调用 API 端点时,它应该以 500 响应,而不是我得到了在测试控制器中引发的异常。我知道在测试中它可能是一个不错的功能,但我不希望这样 - 我想测试控制器的实际行为,它返回内部服务器错误。有没有办法重新配置 TestServer 以返回响应?

控制器动作中的代码无关紧要,可以是throw new Exception();

【问题讨论】:

    标签: c# asp.net-core integration-testing xunit.net


    【解决方案1】:

    您可以创建一个异常处理中间件并在测试中使用它,或者更好地使用它

    public class ExceptionMiddleware
    {
        private readonly RequestDelegate next;
    
        public ExceptionMiddleware(RequestDelegate next)
        {
            this.next = next;
        }
    
        public async Task Invoke(HttpContext httpContext)
        {
            try
            {
                await this.next(httpContext);
            }
            catch (Exception ex)
            {
                httpContext.Response.ContentType = MediaTypeNames.Text.Plain;
                httpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
                await httpContext.Response.WriteAsync("Internal server error!");
            }
        }
    }
    

    现在您可以在 Startup.cs 中注册此中间件:

    ...
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        app.UseMiddleware<ExceptionMiddleware>();
        ...
        app.UseMvc();
    }
    

    如果您不想一直使用它,您可以创建TestStartup - 您的Startup 的子类并覆盖Configure 方法以仅在那里调用UseMiddleware。然后,您将只需要在测试中使用新的 TestStartup 类。

    【讨论】:

    • 只是添加到这个。确保app.UseMiddleware&lt;ExceptionMiddleware&gt;();尽可能靠近Configure方法的顶部,以避免之前抛出异常的可能性。
    • 我这样做了,但由于某些原因,当我将它们与 TestServer 一起使用时,我的 FilterAttributes 中的异常会跳过中间件...
    • 看看Exception filters这个案例
    • 我这样做了,但由于某种原因,我得到的是 404 而不是 500,并且没有调用 catch 块。
    • ...所以当我在我的测试项目中声明TestStartup 时显然会发生404;当我在主网络应用程序项目中声明它时,它可以工作。此问题的答案列出了可能发生这种情况的原因:stackoverflow.com/questions/53438200
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-08
    • 1970-01-01
    相关资源
    最近更新 更多