Search code examples
c#postasp.net-coreintegration-testinginternal-server-error

How to fix 500 Internal Server Error for POST integration tests using TestServer and Antiforgery? ASP.NET Core


I've got a working ASP.NET Core 2.2 implementation that utilizes both MVC and API controllers, and I'm putting together an integration test project to cover everything that has already been tested manually - the basic crud, mostly. Everything works except the tests that use PostAsync to POST data. These tests always get a 500 Internal Server Error as a response from the client, and I cannot for the life of me figure out why. Oi!

The TestServer setup is a pretty standard approach that I've seen on many different blogs and articles. A TestStartup class extends the standard Startup, and overrides the configuration to use in-memory database with seed data. My test fixture base then uses the TestStartup to create a server, and a client, and has a method, which I know works fine, to extract the antiforgery token and add it to forms and headers. All other tests verifying all other aspects of CRUD are working, proving that the seeded data can be retrieved, via both MVC and API calls.

The POST calls that eventually fail with a 500 Internal Server Error do make it into the controller, and the subsequent repository, just fine. With all these aspects in place, I've yet to be able to see the source of the 500.

    [Fact]
    public async void CreatePost_ShouldReturnViewWithNewlyCreatedLabelData()
    {
        // Arrange
        var formData = await EnsureAntiForgeryTokenOnForm(new Dictionary<string, string>()
        {
            { "Name", TestDataGraph.Labels.LabelNew.Name },
            { "WebsiteUrl", TestDataGraph.Labels.LabelNew.WebsiteUrl }
        });

        // Act
        var response = await Client.PostAsync("/labels/create", new FormUrlEncodedContent(formData));

        // Assert
        Assert.Equal(HttpStatusCode.Found, response.StatusCode);
        Assert.Equal("/Labels", response.Headers.Location.ToString());
    }

This is a simple example test in Xunit that attempts to validate the creation of a new simple object, type Label, via MVC route, which follows the standard path format, having been scaffolded. This test will make it into the controller, and its repository, but the response will be a 500 Internal Server Error.

Could I have missed something important in Startup? Any ideas for finding further details about this failure? Thanks in advance! I can post more code or details if they will be helpful.


Solution

  • Try adding trace logging... Trace logging will display activity in the .Net Core framework.

    ...
    public static ILogger<ConsoleLoggerProvider> AppLogger = null;
    public static ILoggerFactory loggerFactory = null;
    //
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddLogging(builder => builder
            .AddConsole()
            .AddFilter(level => level >= LogLevel.Trace)
        );
        loggerFactory = services.BuildServiceProvider().GetService<ILoggerFactory>();
        AppLogger = loggerFactory.CreateLogger<ConsoleLoggerProvider>();
        ...
    

    An example trace log:

    trce: Microsoft.AspNetCore.Mvc.Razor.Internal.RazorViewCompiler[7]
        Could not find a file for view at path '/Views/Home/_Layout.cshtml'.
    

    After you have resolved the issue, change the LogLevel to a more appropriate value.