借力 Xunit.Microsoft.DependencyInjection 开源库,单元测试依赖注入更轻松

今天在写单元测试代码中依赖注入部分时在网上找了找,看有没有对应的开源好库,结果发现了 Xunit.Microsoft.DependencyInjection,现学现用体验了一下,感觉味道不错,在这篇博文中简单记录一下。

安装 nuget 包 Xunit.Microsoft.DependencyInjection

dotnet add package Xunit.Microsoft.DependencyInjection

添加继承自 TestBedFixture 的自定义 fixture BlogClientFixture,向依赖注入容器注册服务的方法在 AddServices 重载方法中添加。

public class BlogClientFixture : TestBedFixture
{
    protected override void AddServices(IServiceCollection services, IConfiguration configuration)
    {
        var handler = new Mock<HttpMessageHandler>();
        services.AddScoped(sp => handler);
        services.AddBlogClient().ConfigurePrimaryHttpMessageHandler(() => handler.Object);

        services.AddLogging(logging => logging.SetMinimumLevel(LogLevel.Warning).AddConsole());
        services.AddSingleton(configuration);
    }

    protected override ValueTask DisposeAsyncCore() => default;

    protected override IEnumerable<TestAppSettings> GetTestAppSettings()
    {
        yield return new() { Filename = "appsettings.json", IsOptional = true };
    }
}

注:AddServices 方法提供了 IConfiguration 参数,可以方便地注册 IConfiguration,很贴心。

在测试用例类 BlogClientTests 中使用 Xunit.Microsoft.DependencyInjection 提供的 TestBed 注入服务

public class BlogClientTests : TestBed<BlogClientFixture>
{
    private readonly BlogClient _blogClient;
    private readonly Mock<HttpMessageHandler> _mockHandler;
    private readonly Uri _baseAddress;

    public BlogClientTests(ITestOutputHelper testOutput, BlogClientFixture fixture)
        : base(testOutput, fixture)
    {
        _blogClient = fixture.GetService<BlogClient>(testOutput);
        _mockHandler = fixture.GetService<Mock<HttpMessageHandler>>(testOutput);
        _baseAddress = new Uri(
            fixture.GetService<IOptions<BlogClientOptions>>(testOutput).Value.BaseAddress);
    }

    [Theory]
    [InlineData(1, 2, 3)]
    public async Task GetPublicPostIds_test(params int[] postIds)
    {
        var publicPostIds = postIds.ToList();
        publicPostIds.Remove(Random.Shared.Next(1, 3));

        var apiClientType = typeof(IBlogPostClient);
        var restMethod = new RestMethodInfo(
            apiClientType,
            apiClientType.GetMethods().First(m => m.Name == nameof(IBlogPostClient.GetPublicPostIds)));

        var requestUri = new Uri(_baseAddress, restMethod.RelativePath);
        _mockHandler.SetupRequest(HttpMethod.Post, requestUri)
            .ReturnsJsonResponse(publicPostIds);

        var actualPostIds = await _blogClient.BlogPosts
            .GetPublicPostIds(postIds);
        Assert.NotEmpty(actualPostIds);
        actualPostIds.Should().BeEquivalentTo(publicPostIds);
    }
}

就这么轻松搞定。

posted @ 2023-01-31 17:06  dudu  阅读(177)  评论(0编辑  收藏  举报