ProblemDetails don't work when the application is started via a WebApplicationFactory (i.e in an integration test)

huangapple go评论71阅读模式
英文:

ProblemDetails don't work when the application is started via a WebApplicationFactory (i.e in an integration test)

问题

我有一个已正确配置为在任何未处理异常时返回ProblemDetails的ASP.NET Core应用程序。这按预期工作,异常被抛出,响应是带有预期的ProblemDetails JSON主体的HTTP500。然而,如果将相同的应用程序作为集成测试的一部分使用WebApplicationFactory<Program>启动,那么在同一失败的请求主体中将不会返回ProblemDetails。整个ProblemDetails机制似乎停止运行。这似乎是一个bug,但我想知道是否有人让这个工作,或者是否有任何解决方法?

供参考,ProblemDetails在Program.cs中启用如下:

services.AddProblemDetails()
app.UseExceptionHandler()
英文:

I have an ASP.NET Core application that is correctly configured to return ProblemDetails upon any unhandled exaception. This works as expected, exception is thrown and the response is a HTTP500 with the expected ProblemDetails JSON body. However, if the same application is spun up as part of a integration test using WebApplicationFactory<Program>, ProblemDetails are not returned in the same failed request body. The whole ProblemDetails mechanism just seems to stop functioning. This seems like a bug but I'm curious if anyone has this working or if there are any workarounds?

For reference, ProblemDetails are enabled in Program.cs with;

services.AddProblemDetails()
app.UseExceptionHandler()

答案1

得分: 0

也许你正在使用 XUnit,它不直接支持控制台输出,但你可以使用 try...catch... 来获取错误消息。

例如:

BasicTests:

public class BasicTests 
    : IClassFixture<WebApplicationFactory<Program>>
{
    private readonly WebApplicationFactory<Program> _factory;
    ITestOutputHelper output;

    public BasicTests(WebApplicationFactory<Program> factory, ITestOutputHelper output)
    {
        _factory = factory;
        this.output= output;
    }

    [Theory]
    [InlineData("/About")]
    public async Task Get_EndpointsReturnSuccessAndCorrectContentType(string url)
    {
        // Arrange
        var client = _factory.CreateClient();
        // Act
        var response = await client.GetAsync(url);
        // Assert
        try
        {
            //不要使用这一行
            //response.EnsureSuccessStatusCode(); // Status Code 200-299
            Assert.Equal(HttpStatusCode.OK, response.StatusCode);

        }
        catch (XunitException e)
        {
            output.WriteLine(e.InnerException.Message);
        }
    }
}

About:

public async Task<IActionResult> OnGet()
{
    throw new NullReferenceException();
}

测试结果:
ProblemDetails don't work when the application is started via a WebApplicationFactory (i.e in an integration test)

另一种方法是不使用 XUnit,而是使用 NUnitMSTest。以 MSTest 为例:

UnitTest1:

[TestClass]
public class UnitTest1
{
    private HttpClient _httpClient;

    public UnitTest1()
    {
        var webAppFactory = new WebApplicationFactory<Program>();
        _httpClient = webAppFactory.CreateDefaultClient();
    }

    [TestMethod]
    public async Task WeatherForcast()
    {
        var response = await _httpClient.GetAsync("/WeatherForecast");
        var stringResult = await response.Content.ReadAsStringAsync();
        response.EnsureSuccessStatusCode();
    }
}

Api:

[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
    private static readonly string[] Summaries = new[]
    {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };

    private readonly ILogger<WeatherForecastController> _logger;

    public WeatherForecastController(ILogger<WeatherForecastController> logger)
    {
        _logger = logger;
    }

    [HttpGet(Name = "GetWeatherForecast")]
    public IEnumerable<WeatherForecast> Get()
    {
        throw new NullReferenceException();
    }
}

测试结果:
ProblemDetails don't work when the application is started via a WebApplicationFactory (i.e in an integration test)

英文:

Maybe you're using XUnit, which doesn't directly support console output, but you can use try...catch... to get error messages.

For example:

BasicTests:

public class BasicTests 
    : IClassFixture&lt;WebApplicationFactory&lt;Program&gt;&gt;
{
    private readonly WebApplicationFactory&lt;Program&gt; _factory;
    ITestOutputHelper output;

    public BasicTests(WebApplicationFactory&lt;Program&gt; factory, ITestOutputHelper output)
    {
        _factory = factory;
        this.output= output;
    }

    [Theory]
    [InlineData(&quot;/About&quot;)]
    public async Task Get_EndpointsReturnSuccessAndCorrectContentType(string url)
    {
        // Arrange
        var client = _factory.CreateClient();
        // Act
        var response = await client.GetAsync(url);
        // Assert
        try
        {
            //don&#39;t use this line
            //response.EnsureSuccessStatusCode(); // Status Code 200-299
            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
            
        }
        catch (XunitException e)
        {
            output.WriteLine(e.InnerException.Message);
        }
    }
}

About:

public async Task&lt;IActionResult&gt; OnGet()
{
    throw new NullReferenceException();
}

Test Result:
ProblemDetails don't work when the application is started via a WebApplicationFactory (i.e in an integration test)

Another way is to not use XUnit, use NUnit or MSTest. Take MSTest as an example:

UnitTest1:

[TestClass]
public class UnitTest1
{
    private HttpClient _httpClient;

    public UnitTest1()
    {
        var webAppFactory = new WebApplicationFactory&lt;Program&gt;();
        _httpClient = webAppFactory.CreateDefaultClient();
    }

    [TestMethod]
    public async Task WeatherForcast()
    {
        var response = await _httpClient.GetAsync(&quot;/WeatherForecast&quot;);
        var stringResult = await response.Content.ReadAsStringAsync();
        response.EnsureSuccessStatusCode();
    }
}

Api:

[ApiController]
[Route(&quot;[controller]&quot;)]
public class WeatherForecastController : ControllerBase
{
    private static readonly string[] Summaries = new[]
    {
    &quot;Freezing&quot;, &quot;Bracing&quot;, &quot;Chilly&quot;, &quot;Cool&quot;, &quot;Mild&quot;, &quot;Warm&quot;, &quot;Balmy&quot;, &quot;Hot&quot;, &quot;Sweltering&quot;, &quot;Scorching&quot;
};

    private readonly ILogger&lt;WeatherForecastController&gt; _logger;

    public WeatherForecastController(ILogger&lt;WeatherForecastController&gt; logger)
    {
        _logger = logger;
    }

    [HttpGet(Name = &quot;GetWeatherForecast&quot;)]
    public IEnumerable&lt;WeatherForecast&gt; Get()
    {
        throw new NullReferenceException();
    }
}

Test Result:
ProblemDetails don't work when the application is started via a WebApplicationFactory (i.e in an integration test)

答案2

得分: 0

这是.NET 7中的一个错误,在8中已修复。

英文:

This is a bug in .NET 7, fixed in 8.

huangapple
  • 本文由 发表于 2023年6月19日 18:23:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/76505712.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定