Skip to content

Extensions and utility code for testing ASP.NET Core web applications

License

Notifications You must be signed in to change notification settings

shaynevanasperen/Fun.AspNetCore.Mvc.Testing

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Build status Join the chat at https://gitter.im/Fun-AspNetCore-Mvc-Testing License

NuGet NuGet

Fun.AspNetCore.Mvc.Testing

A set of libraries for eliminating boilerplate code in web application tests. The main innovation here is that we provide an extensible WebApplicationFactory<TEntryPoint>. The problem with the default one is that it requires us to subclass it for each way that we'd like to configure our web application (for each fixture, or suite of similar tests). This is not practical, because we often need to configure our application in different ways, and we'd like to be able to define that configuration composably from within the test classes themselves. We can't just make our test classes derive from WebApplicationFactory<TEntryPoint>, as then we'd be creating a new instance of our web application for each test!

We want to share a single instance of our web application per test suite rather than per test, but allow the test class to define how that web application is configured. The included ExtensibleWebApplicationFactory<TEntryPoint> class allows us to do just that, and in a beautifully composable way that eliminates boilerplate code and keeps our tests clean and DRY.

Create your base class similar to this:

public abstract class WebApplicationTests : XunitWebApplicationTests<Startup> // implements IClassFixture<ExtensibleWebApplicationFactory<TEntryPoint>>
{
    protected WebApplicationTests(ExtensibleWebApplicationFactory<Startup> factory, ITestOutputHelper testOutputHelper)
        : base(factory, testOutputHelper)
    {
        factory.AfterConfigureAppConfiguration((context, builder) => builder.AddInMemoryCollection(new Dictionary<string, string>
        {
            { "Some.Setting", "FakeValue" }
        }));
        factory.AfterConfigureServices(services =>
        {
            services.AddHttpRequestInterceptor(InterceptHttp);
            services.ReplaceLoggerFactoryWithXUnit(testOutputHelper);
        });
    }

    protected HttpClientInterceptorOptions InterceptHttp { get; } = new HttpClientInterceptorOptions().ThrowsOnMissingRegistration();
}

And then add further customization in a test class:

public class FooTests : WebApplicationTests
{
    protected WebApplicationTests(ExtensibleWebApplicationFactory<Startup> factory, ITestOutputHelper testOutputHelper)
        : base(factory, testOutputHelper)
    {
        // The configurations we apply here are composed on top of those performed by the base class
        factory.AfterConfigureAppConfiguration((context, builder) => builder.AddInMemoryCollection(new Dictionary<string, string>
        {
            { "Other.Setting", "OtherFakeValue" }
        }));
        factory.AfterConfigureServices(services =>
        {
            services.ReplaceDatabaseWithAFake();
            services.ReplaceFooServiceWithAFake();
            services.AddTransient<ITestScopeProducer>(provider =>
                new TestScopeProducer<IDisposable>(provider.GetRequiredService<FakeDbScope>().BeginScope, x => x.Dispose));
        });
    }

    [Fact]
    public async void FooWorks()
    {
        using var scope = App.BeginTestScope();
        
        HttpRequests.Intercept
            .For(x => x.RequestUri.Host == "some.web.api/external-dependency")
            .Responds()
            .WithStatus(HttpStatusCode.NotModified)
            .RegisterWith(Interceptor);

        var response = await App.Client.GetAsync("foo/check");
        response.IsSuccessStatusCode.Should().BeTrue();
    }
}

About

Extensions and utility code for testing ASP.NET Core web applications

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages