Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/280.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/329.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在ASP.NETCore中测试全局错误处理中间件和控制器之间的集成?_C#_Asp.net Core_Xunit - Fatal编程技术网

C# 如何在ASP.NETCore中测试全局错误处理中间件和控制器之间的集成?

C# 如何在ASP.NETCore中测试全局错误处理中间件和控制器之间的集成?,c#,asp.net-core,xunit,C#,Asp.net Core,Xunit,我正试图用XUnit编写一些测试,特别是我希望有一个测试,确保当抛出某个异常时,它会被重新映射到一个有意义的错误代码中。 我已经设置了全局错误处理中间件,它工作正常。 下面是我的解决方案工作原理的一些示例代码: 我的控制器有一个post端点,可以返回200或404 //Controller [HttpPost] [ProducesResponseType(200)] [ProducesResponseType(404)] public async Task<StatusCodeResult

我正试图用XUnit编写一些测试,特别是我希望有一个测试,确保当抛出某个异常时,它会被重新映射到一个有意义的错误代码中。 我已经设置了全局错误处理中间件,它工作正常。 下面是我的解决方案工作原理的一些示例代码:

我的控制器有一个post端点,可以返回200或404

//Controller
[HttpPost]
[ProducesResponseType(200)]
[ProducesResponseType(404)]
public async Task<StatusCodeResult> Create([FromBody] Request request) {
    //Process request
    handler.Handle(request);
    return Ok();
}
//控制器
[HttpPost]
[产品响应类型(200)]
[产品响应类型(404)]
公共异步任务创建([FromBody]请求){
//处理请求
处理(请求);
返回Ok();
}
用于将异常重新映射为错误代码的全局错误处理的中间件

//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());
        }
    });
});
//启动中间件
app.UseExceptionHandler(生成器=>{
Run(处理程序:异步上下文=>{
IEExceptionHandlerFeature错误=context.Features.Get();
if(错误!=null){
int statusCode=(int)GetStatusCodeForException(error.error);
context.Response.StatusCode=状态码;
context.Response.ContentType=“应用程序/json”;
wait context.Response.WriteAsync(新的错误详细信息{StatusCode=StatusCode,Message=error.error.Message}.ToString());
}
});
});
然后在测试中,我安排一些模拟,实例化控制器并调用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);
}
//单元测试
[事实]
公共异步任务测试()
{
//安排
var mockHandler=new Mock();
mockHandler.Setup(handler=>handler.Handle(It.IsAny()).Throws(newcustomexception(It.IsAny()));
MyController MyController=新的MyController();
//表演
var statusCodeResult=等待myController.Create(请求);
//断言
StatusCodeResult=Assert.IsType(StatusCodeResult);
}

这里我想确保CustomException被重新映射到404状态代码中。我该怎么做?感谢您的帮助

在您的测试中,中间件不可用。要实现这一点,您需要启动一个托管环境,Microsoft.AspNetCore.TestHost包提供了一个可用于测试的环境:

[事实]
公共异步任务Test1()
{
使用var host=newtestserver(Program.CreateHostBuilder(null));
var client=host.CreateClient();
var requestMessage=newhttprequestmessage(HttpMethod.Get,“/api/controller”);
var result=await client.sendsync(requestMessage);
var status=result.StatusCode;
//TODO:断言
}

现在,当您以引发异常的方式调用API时,应该执行并覆盖中间件。

在您的测试中,中间件不可用。要实现这一点,您需要启动一个托管环境,Microsoft.AspNetCore.TestHost包提供了一个可用于测试的环境:

[事实]
公共异步任务Test1()
{
使用var host=newtestserver(Program.CreateHostBuilder(null));
var client=host.CreateClient();
var requestMessage=newhttprequestmessage(HttpMethod.Get,“/api/controller”);
var result=await client.sendsync(requestMessage);
var status=result.StatusCode;
//TODO:断言
}
现在,当您以引发异常的方式调用API时,应该执行并覆盖中间件。

您可以使用Microsoft.AspNetCore.Mvc.Testing nuget包中的类。这将在内存中引导应用程序,以允许端到端功能测试。您可以通过
HttpClient
进行调用,以确保调用所有中间件等,而不是调用单个操作方法

您使用已在主条目项目中定义的
Startup
类,并且可以根据需要将模拟/伪对象添加到IoC容器中。这允许您验证/设置任何依赖项

然后可以将其作为
IClassFixture
注入。注入后,在实例上调用
.CreateClient()
将返回一个
HttpClient
,您可以通过它发出请求

下面是一个示例实现:

// 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
    }
}
//应用程序工厂实例
公共类TestAppFactory:WebApplicationFactory
{
//用于设置/验证的模拟
公共Mock MockHandler{get;}=new Mock();
受保护的覆盖无效配置WebHost(IWebHostBuilder)
{
builder.ConfigureTestServices(服务=>
{
AddSingleton(MockHandler);
});
}
}
公共类MyTestClass:IClassFixture
{
私有只读TestAppFactory\u工厂;
私有只读HttpClient\u客户端;
私有只读Mock\u mockHandler;
公共MyTestClass(TestAppFactory工厂)
{
_工厂=工厂;
_client=factory.CreateClient();
_mockHandler=factory.mockHandler;
}
[事实]
公共异步任务测试()
{
//通过客户机拨打电话
}
}
您可以使用Microsoft.AspNetCore.Mvc.Testing nuget包中的类。这将在内存中引导应用程序,以允许端到端功能测试。您可以通过
HttpClient
进行调用,以确保调用所有中间件等,而不是调用单个操作方法

您使用已在主条目项目中定义的
Startup
类,并且可以根据需要将模拟/伪对象添加到IoC容器中。这允许您验证/设置任何依赖项

然后可以将其作为
IClassFixture
注入。注入后,在实例上调用
.CreateClient()
将返回一个
HttpClient
,您可以通过它发出请求

下面是一个示例实现:

// 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
    }
}
//应用程序工厂实例
公共类TestAppFactory:WebApplicationFactory
{
//用于设置/验证的模拟
公共Mock MockHandler{get;}=new Mock();
受保护的覆盖无效配置WebHost(IWebHostBuilder)
{