[聚合文章] 体验 ASP.NET Core 集成测试三剑客:xUnit.net、TestServer、EF Core InMemory

.Net 2018-01-07 17 阅读

这是昨天解决的一个问题,针对一个 web api 的客户端代理类写集成测试,既要测试 web api,又要测试 web api 客户端。

测试 web api,就要在运行测试时自动启动 web api 站点,asp.net core 中的 TestServer 就是为此而生,而且与 asp.net core 结合的天衣无缝,不仅自己可以通过I WebHostBuilder 配置站点,而且可以直接使用 web api 站点的 Startup 类。

对于测试时的数据模拟,可以通过 EF Core 提供的 InMemory database ,使用起来超级简单,只需在依赖注入 DbContext 时使用 options.UseInMemoryDatabase() 。

而对于 TestServer 的统一管理(配置、启动、销毁),对所测试的类的依赖注入,可以借助 xUnit.net 的 fixture class ,详见 Shared Context between Tests

xUnit.net fixture class 的示例代码如下:

public class WebApiTestFixture : IDisposable
{
    private readonly TestServer _testServer;

    public WebApiTestFixture()
    {
        IWebHostBuilder webHostBuilder = WebHost.CreateDefaultBuilder()
            .ConfigureLogging((logging) =>
            {
                logging.AddConsole();
            })
            .ConfigureServices(services =>
            {
                services.AddSingleton<IMemcachedClient, NullMemcachedClient>();
                services.AddDbContext<UCenterDbContext>(options =>
                {
                    options.UseInMemoryDatabase("UCenter");
                });
            })
            .UseStartup<Startup>();

        _testServer = new TestServer(webHostBuilder);
        ServerServices = _testServer.Host.Services;

        ConfigureClientServices(_testServer.CreateClient());
    }

    public IServiceProvider ClientServices { get; private set; }
    public IServiceProvider ServerServices { get; private set; }

    private void ConfigureClientServices(HttpClient httpClient)
    {
        IServiceCollection services = new ServiceCollection();
        services.AddSingleton<IMemcachedClient, NullMemcachedClient>();
        services.AddLogging(builder => builder.AddConsole());
        services.AddSingleton(httpClient);
        services.AddSingleton<IUCenterService, UCenterService>();
        ClientServices = services.BuildServiceProvider();
    }

    public void Dispose()
    {
        _testServer.Dispose();
    }
}

集成测试的示例代码如下:

public class UCenterServiceTests : IClassFixture<WebApiTestFixture>
{
    private readonly IUCenterService _ucenterService;
    private readonly UCenterDbContext _dbContext;

    public UCenterServiceTests(WebApiTestFixture fixture)
    {
        _ucenterService = fixture.ClientServices.GetService<IUCenterService>();
        _dbContext = fixture.ServerServices.GetService<UCenterDbContext>();
    }

    [Fact]
    public async Task GetUserTest()
    {
        var fakeUser = new User
        {
            DisplayName = "博客园团队",
            BlogApp = "cmt"
        };
        _dbContext.Users.Add(fakeUser);
        (await _dbContext.SaveChangesAsync()).ShouldBeGreaterThan(0);

        var user = await _ucenterService.GetUser(u => u.DisplayName, fakeUser.DisplayName);
        user.ShouldNotBeNull();
        user.BlogApp.ShouldBe(fakeUser.BlogApp);
    }
}

注:本文内容来自互联网,旨在为开发者提供分享、交流的平台。如有涉及文章版权等事宜,请你联系站长进行处理。