Confirm that middleware is in use
Asked Answered
W

3

8

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!

Wigging answered 1/5, 2018 at 12:56 Comment(0)
Y
9

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.

Young answered 1/5, 2018 at 13:10 Comment(2)
I was afraid of this but it appears I would have to do that to test it. It's a shame that there is not an IApplicationBuilder or IServiceProvider method that gives you the pipeline or confirms whether or not a specific class (or even interface) is in the pipeline.Wigging
Well, as I said, you can easily test that IApplicationBuilder.Use was called, but due to how UseMiddleware works, you simply won’t be able to tell that it’s the middleware of your type. At least not without actually invoking the request delegate.Young
A
1

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.

Abby answered 1/5, 2018 at 13:33 Comment(0)
M
0

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.

Mcdonnell answered 21/5, 2020 at 16:56 Comment(3)
What version of .Net Core do you use with this test? Doesn't work for me with .Net Core 3.1.Muncey
It is .net core 3.1Mcdonnell
With assuming there is only one middleware in the list you cant create integration tests.Compotation

© 2022 - 2024 — McMap. All rights reserved.