借力 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);
}
}
就这么轻松搞定。