Search code examples
c#.net.net-corexunit

.NET Core TestServer returns status 200 instead of 404 for post request to non-existent path


I am implementing integration tests for a .NET Core 3.1 application using the following guide: https://learn.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-3.1. This is my current test class:

public class IntegrationTests : IClassFixture<WebApplicationFactory<main_app.Startup>>
{
    private readonly WebApplicationFactory<main_app.Startup> _factory;

    public TestTest(WebApplicationFactory<main_app.Startup> factory) {
        _factory = factory;
    }

    [Fact]
    public async void GetBogusPath() {
        var client = _factory.CreateClient();
        var response = await client.GetAsync("ofajspd");
        Assert.False(response.IsSuccessStatusCode);
    }

    [Fact]
    public async void PostBogusPath() {
        var client = _factory.CreateClient();
        var request_body = new StringContent("{}", Encoding.UTF8, "application/json");
        var response = await client.PostAsync("ofajspd", request_body);
        Assert.False(response.IsSuccessStatusCode);
    }
}

The get request test acts as expected, in that it returns a 404 status code. However, the post request returns a 200 status, even though the path doesn't exist. What could be causing this problem, and how do I resolve it?

If I run the server locally and fire post requests at a non-existent endpoint manually, it acts as expected, so the problem is limited to just these integration tests.

EDIT: Here's my controller class definition:

[ApiController]
[ApiVersion("1")]
[Route("v{version:apiVersion}/[controller]")]
public class QueryController : ControllerBase
{
    [AcceptVerbs("Post")]
    public async Task<QueryResponse> Post([FromBody]QueryRequest rq) {
        return await QueryHandler.HandlePost(rq, this.HttpContext);
    }
}

Solution

  • The problem was that I had attached a custom piece of middleware in Startup.cs that had a bug, so it was swallowing 404s generated by other middleware and outputting 200s instead. It was supposed to be handling a specific type of error, but the bug caused it to handle a much wider array of errors than intended. Removing the faulty middleware fixed the problem.

    For extra detail, the custom middleware in question was checking for a specific 'HResult' in exceptions thrown by other middleware layers, but the HResult value referred to an AggregateException that was thrown much more often than the specific error I was looking for (which was writing to a response after it had already begun streaming).