Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Configure AspNetCore TestServer to return 500 instead of throwing exception

I am developing a Web API that in some cases will respond with 500 (ugly design, I know, but can't do anything about it). In tests there's an ApiFixture that contains AspNetCore.TestHost:

public class ApiFixture
{
    public TestServer ApiServer { get; }
    public HttpClient HttpClient { get; }

    public ApiFixture()
    {
        var config = new ConfigurationBuilder()
            .AddEnvironmentVariables()
            .Build();

        var path = Assembly.GetAssembly(typeof(ApiFixture)).Location;
        var hostBuilder = new WebHostBuilder()
            .UseContentRoot(Path.GetDirectoryName(path))
            .UseConfiguration(config)
            .UseStartup<Startup>();

        ApiServer = new TestServer(hostBuilder);
        HttpClient = ApiServer.CreateClient();
    }
}

When I am calling API endpoint with HttpClient from this fixture it should respond with 500, instead I am getting exception that is being raised in the tested controller. I know that in tests it might be a nice feature, but I don't want that - I want to test actual behavior of controller, which is returning internal server error. Is there a way to reconfigure TestServer to return response?

Code in controller action is irrelevant, can be throw new Exception();

like image 872
deha Avatar asked Nov 28 '18 07:11

deha


People also ask

How do you handle exceptions globally in .NET core?

Use the UseExceptionHandler middleware in ASP.NET Core So, to implement the global exception handler, we can use the benefits of the ASP.NET Core build-in Middleware. A middleware is indicated as a software component inserted into the request processing pipeline which handles the requests and responses.


1 Answers

You can create an exception handling middleware and use it in tests or better always

public class ExceptionMiddleware
{
    private readonly RequestDelegate next;

    public ExceptionMiddleware(RequestDelegate next)
    {
        this.next = next;
    }

    public async Task Invoke(HttpContext httpContext)
    {
        try
        {
            await this.next(httpContext);
        }
        catch (Exception ex)
        {
            httpContext.Response.ContentType = MediaTypeNames.Text.Plain;
            httpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
            await httpContext.Response.WriteAsync("Internal server error!");
        }
    }
}

Now you can register this middleware in your Startup.cs:

...
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.UseMiddleware<ExceptionMiddleware>();
    ...
    app.UseMvc();
}

And if you don't want to use it all the time you can create TestStartup - a child class of your Startup and override Configure method to call UseMiddleware only there. Then you will need to use the new TestStartup class in the tests only.

like image 199
Pavel Agarkov Avatar answered Oct 02 '22 14:10

Pavel Agarkov