简体   繁体   English

如何在 ASP.Net Core 中测试全局错误处理中间件与我的 controller 之间的集成?

[英]How do I test the integration between the Global error handling middleware and my controller in ASP.Net Core?

I'm trying to write some test with XUnit, specifically I'd like to have a test that ensures that when a certain exception is thrown it gets remapped into a meaningful error code.我正在尝试用 XUnit 编写一些测试,特别是我想要一个测试,以确保当某个异常被抛出时,它会被重新映射到一个有意义的错误代码中。 I already set up the Global error handling middleware and it works correctly.我已经设置了全局错误处理中间件,它可以正常工作。 Here there is some example code of how my solution works:这里有一些关于我的解决方案如何工作的示例代码:

My controller with a post endpoint that can return 200 or 404我的 controller 带有可以返回 200 或 404 的后端点

//Controller
[HttpPost]
[ProducesResponseType(200)]
[ProducesResponseType(404)]
public async Task<StatusCodeResult> Create([FromBody] Request request) {
    //Process request
    handler.Handle(request);
    return Ok();
}

The Middleware for the Global error handling that remaps exceptions into Error codes用于将异常重新映射为错误代码的全局错误处理中间件

//StartUp Middleware
app.UseExceptionHandler(builder => {
    builder.Run(handler: async context => {
        IExceptionHandlerFeature error = context.Features.Get<IExceptionHandlerFeature>();
        if (error != null) {
            int statusCode = (int)GetStatusCodeForException(error.Error);
            context.Response.StatusCode = statusCode;
            context.Response.ContentType = "application/json";

            await context.Response.WriteAsync(new ErrorDetails { StatusCode = statusCode, Message = error.Error.Message }.ToString());
        }
    });
});

And then my test in where I arrange some mocks, instantiate the controller and call the Create method然后在我安排一些模拟的地方进行测试,实例化 controller 并调用 Create 方法

//UnitTest
[Fact]
public async Task Test()
{
    //Arrange
    var mockHandler = new Mock<IHandler>();
    mockHandler.Setup(handler => handler.Handle(It.IsAny<Request>())).Throws(new CustomException(It.IsAny<string>()));

    MyController myController = new MyController();

    //Act
    var statusCodeResult = await myController.Create(request);

    //Assert
    StatusCodeResult result = Assert.IsType<NotFoundResult>(statusCodeResult);
}

Here I want to ensure that the CustomException is remapped into a 404 status code.在这里,我要确保将 CustomException 重新映射为 404 状态代码。 How do I do it?我该怎么做? Any help is appreciated.任何帮助表示赞赏。

In your test the middleware is not available.在您的测试中,中间件不可用。 You need to spin up a hosting environment to do that, the package Microsoft.AspNetCore.TestHost provides you with one that you can use for testing:您需要启动一个托管环境来执行此操作,package Microsoft.AspNetCore.TestHost为您提供了一个可用于测试的环境:

[Fact]
public async Task Test1()
{
    using var host = new TestServer(Program.CreateHostBuilder(null));
    var client = host.CreateClient();

    var requestMessage = new HttpRequestMessage(HttpMethod.Get, "/api/controller");

    var result = await client.SendAsync(requestMessage);

    var status = result.StatusCode;

    // TODO: assertions
}

Now when you call your API in a way an exception is thrown, the middleware should be executed and covered.现在,当您以引发异常的方式调用 API 时,应该执行并覆盖中间件。

You can use the WebApplicationFactory class from the Microsoft.AspNetCore.Mvc.Testing nuget package.您可以使用 Microsoft.AspNetCore.Mvc.Testing nuget package 中的WebApplicationFactory class。 This bootstraps your application in-memory to allow for end to end functional tests.这会在内存中引导您的应用程序,以允许进行端到端的功能测试。 Rather than calling individual action methods you can make calls via HttpClient to ensure all middleware etc is called.您可以通过HttpClient进行调用,而不是调用单独的操作方法,以确保调用所有中间件等。

You use the Startup class that you have already defined in your main entry project and can add mock/fake objects to the IoC container as required.您使用已在主入口项目中定义的Startup class 并可以根据需要将模拟/伪造对象添加到 IoC 容器。 This allows you to verify/setup any dependencies.这允许您验证/设置任何依赖项。

You can then inject this as an IClassFixture .然后,您可以将其作为IClassFixture注入。 Once injected calling .CreateClient() on the instance will return an HttpClient , through which you can make requests.一旦在实例上注入调用.CreateClient()将返回一个HttpClient ,您可以通过它发出请求。

Here is an example implementation:这是一个示例实现:

// app factory instance
public class TestAppFactory : WebApplicationFactory<Startup>
{
    // mock for setup/verify
    public Mock<IHandler> MockHandler { get; } = new Mock<IHandler>();

    protected override void ConfigureWebHost(IWebHostBuilder builder)
    {
        builder.ConfigureTestServices(services =>
        {
            services.AddSingleton(MockHandler);
        });
    }
}

public class MyTestClass : IClassFixture<TestAppFactory>
{
    private readonly TestAppFactory _factory;
    private readonly HttpClient _client;
    private readonly Mock<IHandler> _mockHandler;

    public MyTestClass(TestAppFactory factory)
    {
        _factory = factory;
        _client = factory.CreateClient();
        _mockHandler = factory.MockHandler;
    }

    [Fact]
    public async Task Test()
    {
        // make calls via _client
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 我如何告诉 MVC 中间件我的 class 是 ASP.NET Core 中的一个 Controller? - How do I tell the MVC middleware that my class is a Controller in ASP.NET Core? 如何在我上传文件的Asp.Net核心web api端点上进行集成测试? - How to do an integration test on my Asp.Net core web api endpoint where I upload a file? ASP.NET Core 3.1 中的自定义错误处理中间件? - Custom error handling middleware in ASP.NET Core 3.1? ASP.Net Core 异常处理中间件 - ASP.Net Core exception handling middleware ASP.NET Core MVC 中的全局错误处理 - Global Error Handling in ASP.NET Core MVC ASP.NET MVC Core和Dapper中的全局异常/错误处理 - Global exception/error handling in asp.net mvc core and dapper 使用中间件的全局异常处理在 ASP.Net Core 应用程序中不起作用 - Global Exception Handling using Middleware not working in ASP.Net Core app 如何从 Z9E0DA8438E1E38A1C30F4B76CE73B8 页面调用我的 API controller object? - How do I call my API controller object from an ASP.NET Core page? 我需要在 asp.net Core 中创建 XSRF 中间件吗? - Do I need to create an XSRF middleware in asp.net Core? 如何在 ASP.NET Core 中测试 https 重定向? - How do I test an https redirect in ASP.NET Core?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM