Skip to content

Ammending the request pipeline with WebApplicationFactory #3254

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
chris-brown opened this issue Jun 22, 2018 · 5 comments
Closed

Ammending the request pipeline with WebApplicationFactory #3254

chris-brown opened this issue Jun 22, 2018 · 5 comments

Comments

@chris-brown
Copy link

chris-brown commented Jun 22, 2018

dotnet/AspNetCore.Docs#7203

Im trying to create a integration test for my Exception handling middleware How do you add to the existing ApplicationBuilder with WebApplicationFactory?

Im using WebApplicationFactory<T> with my Startup.cs and I want to add an additional middleware to the request pipeline so I can mimic a error response.

The example below completely overrides my Startup which is not the desired result. I noticed builder has the following extension methods ConfigureTestServices() and ConfigureTestContainer() but there doesnt appear to be an equivilant to configure the request pipeline thats under test.

_client = fixture.WithWebHostBuilder(builder =>
{
   builder.Configure(app =>
   {
      app.Map("/error", a => a.Run(c => throw new Exception("My error message")));
   });
}).CreateDefaultClient();

Perhaps I could use a IStartupFilter which throws at the end of the request pipeline. But im not sure how I could get that to invoke after my middleware.

This seems to do it but its alot of boiler plate. I'm hoping im missing something obvious.

    public class ErrorsController : Controller
    {
        [Route("Error")]
        public IActionResult Error() => throw new Exception();
    }

    public class ExceptionMiddlewareTests : IClassFixture<WebApplicationFactory<Startup>>
    {
        private readonly HttpClient _client;

        public ExceptionMiddlewareTests(WebApplicationFactory<Startup> fixture)
        {
            _client = fixture.WithWebHostBuilder(builder =>
            {
                builder.ConfigureTestServices(collection =>
                {
                    var mvc = collection.AddMvc();
                    var parts = mvc.PartManager.ApplicationParts;
                    parts.Clear();
                    parts.Add(new AssemblyPart(typeof(Startup).GetTypeInfo().Assembly));
                    parts.Add(new AssemblyPart(GetType().Assembly));
                });
            }).CreateDefaultClient();
        }
        // ...
@chris-brown
Copy link
Author

@ardalis @javiercn @guardrex hoping either of you can point me in the right direction?

@ardalis
Copy link
Contributor

ardalis commented Jun 22, 2018

You have to subclass WebApplicationFactory<T> so that you can override its protected method ConfigureWebHost as shown here: https://docs.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-2.1#customize-webapplicationfactory

@chris-brown
Copy link
Author

chris-brown commented Jun 22, 2018

Can you provide an example @ardalis as the following doesnt work.

   public class MiddlewareTestFixture : WebApplicationFactory<Startup>
    {
        protected override void ConfigureWebHost(IWebHostBuilder builder)
        {
            // this line prevents Startup.Configure from firing
            builder.Configure(app =>
            {
                app.Map("/error", applicationBuilder => { applicationBuilder.Run(_ => throw new Exception()); });
            });
            base.ConfigureWebHost(builder);
        }
    }

    public class Test : IClassFixture<MiddlewareTestFixture>
    {
        private readonly HttpClient _client;

        public Test(MiddlewareTestFixture fixture)
        {
            _client = fixture.CreateClient();
        }

        [Fact]
        public async Task Me()
        {
            var result = await _client.GetAsync("/error");
            result.StatusCode.ShouldBe(HttpStatusCode.InternalServerError);
        }
    }

As soon as I use builder.Configure(app => ... then Configure in my Startup.cs doesn't get executed. Im trying to add to the existing request pipeline that was defined in my startup.

@ardalis
Copy link
Contributor

ardalis commented Jun 22, 2018

You're correct that any call to builder.Configure will override Startup.Configure. I think you might want to try a different approach, such as specifying an environment (e.g. Testing) and in Startup checking that environment and modifying the request pipeline accordingly. Alternately, just create a controller action that you know throws an exception and hit that in your test.

@javiercn
Copy link
Member

The controller action or the custom environment are the ways to go. Getting in the middle of the pipeline through the use of services is not possible.

@Eilon Eilon closed this as completed Jul 13, 2018
@ghost ghost locked as resolved and limited conversation to collaborators Dec 3, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants