Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Confirm that middleware is in use

I am trying to confirm via a unit test that middleware is actually being added to the pipeline. I have the following static method that adds the middleware. This is what I am testing.

public static class HandleDbUpdateExceptionExtensions
{
    public static IApplicationBuilder UseDbUpdateExceptionHandler(this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<DbUpdateExceptionHandler>();
    }
}

I know it's actually working because the middleware runs on my site. However, I'd like to write a unit test to ensure it's always included in future builds. My unit test, however, fails:

[Fact(DisplayName = "Exception handler is added to IApplicationBuilder")]
public void DbUpdateExceptionHandler_Added_To_IApplicationBuilder()
{
    var builder = new Mock<IApplicationBuilder>().Object;

    builder.UseDbUpdateExceptionHandler();

    Assert.NotNull(builder.ApplicationServices);

    //var test = builder.ApplicationServices.GetService(typeof(DbUpdateExceptionHandler));
}

builder.ApplicationServices is null so the test currently fails. I assume that it is failing because I am just mocking IApplicationBuilder but there is very little relevant material online about unit testing the existance of .Net Core middleware.

Any help is greatly appreciated!

like image 914
Phillip Copley Avatar asked May 01 '18 12:05

Phillip Copley


3 Answers

UseMiddleware is actually an extension method that will create a RequestDelegate that uses your middleware internally. That delegate does quite a lot of things, so it would be very difficult for you to test that it will properly register your actual middleware type.

The only thing you can really do is to check that the underlying ApplicationBuilder.Use method was called with some request delegate.

Alternatively, you could also actually invoke the middleware, by building the application pipeline and executing it. But that will require that you set up dependency injection properly (since the delegate from UseMiddleware() will use that) and that all your middleware’s dependencies are set up properly.

So this is going to be very complicated. I would suggest you to write an integration test instead that checks that for a request, your middleware will be invoked properly and can do what it should do.

like image 112
poke Avatar answered Sep 28 '22 04:09

poke


In addition to @poke's answer you might want to look into middleware analysis which is part of the ASP.NET Core Diagnostics stack. There is also a sample application available.

What it basically does is surrounding each middleware with the AnalysisMiddleware which writes information to a diagnostics source. You could create a diagnostics source listener in your tests and validate that each middleware is invoked. However, this requires you to execute the middleware pipeline which effectively means your creating an integration test.

like image 30
Henk Mollema Avatar answered Sep 28 '22 03:09

Henk Mollema


Here is the way I've done it:

var serviceCollection = new ServiceCollection();
serviceCollection.AddSingleton(Mock.Of<ILogger<ExceptionHandlingMiddleware>>());

var applicationBuilder = new ApplicationBuilder(serviceCollection.BuildServiceProvider());

applicationBuilder.UseExceptionHandlingMiddleware();

var app = applicationBuilder.Build();

app.Target.Should().BeOfType<ExceptionHandlingMiddleware>();

This works when there is only one middleware in the list.

like image 44
delepster Avatar answered Sep 28 '22 04:09

delepster