GitXplorerGitXplorer
s

Fun.AspNetCore.Mvc.Testing

public
2 stars
0 forks
0 issues

Commits

List of commits on branch master.
Unverified
44fd50548a0c5e5c18ec0056d0902b448287e1b4

Fix lifetime problem with HttpClientInterceptorOptions

sshaynevanasperen committed 4 years ago
Unverified
7842d8ed1c2c024e043298454dad6e236f6070b9

Allow consumers to specify the interception options prior to app startup

sshaynevanasperen committed 4 years ago
Unverified
c3162599079e9cd1f66a694b58061cb512c99e2e

Reference latest version of Fun.AspNetCore.Mvc.Testing from dependent packages

sshaynevanasperen committed 4 years ago
Unverified
a6118b1c83c17f518e4fc44923e93971f664a9a8

Expose the IWebHostBuilder itself for additional flexibility

sshaynevanasperen committed 4 years ago
Unverified
3928a48fbfe1b6da48304a13f84d5177da515640

Control dependency versions manually for Release builds

sshaynevanasperen committed 4 years ago
Unverified
268b3bd11669d7ac59ba8f65de75b219afcb9546

Add all three libraries, with README and all associated files

sshaynevanasperen committed 4 years ago

README

The README file for this repository.

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();
    }
}