C# の xUnit を使用し、WebApplicationFactory
を活用して 個別ケースごとに異なるモックを適用 する結合テストの実装方法を解説。
WebApplicationFactory<T>
を活用し、本番に近い形でWeb APIの動作をテストWebApplicationFactory
の基本構造まずは、基本的な WebApplicationFactory
のカスタマイズ方法。
SampleWebApplicationFactory.cs
(カスタムWebApplicationFactory)// SampleWebApplicationFactory.cs
using System;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.Extensions.DependencyInjection;
public class SampleWebApplicationFactory : WebApplicationFactory<Program>
{
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.ConfigureServices(services =>
{
// 個別テストごとにサービスを上書きするため、ここではデフォルトの設定のみ
});
}
}
ConfigureWebHost
で DIコンテナをカスタマイズ
モックは個別のテストケースで適用するため、ここでは設定を追加しない
WebApplicationFactory
を活用したモック適用次に、テストケースごとに異なるモックをセット する方法。
SampleTest.cs
(結合テスト)// SampleTest.cs
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Moq;
using Xunit;
public class SampleTest : IClassFixture<SampleWebApplicationFactory>
{
private readonly HttpClient _httpClient;
private readonly SampleWebApplicationFactory _factory;
public SampleTest(SampleWebApplicationFactory factory)
{
_factory = factory;
_httpClient = factory.CreateClient();
}
[Fact]
public async Task UploadFile_Should_Call_FileUploader()
{
// Arrange
var fileUploaderMock = new Mock<IFileUploader>();
fileUploaderMock.Setup(u => u.UploadAsync(It.IsAny<byte[]>())).ReturnsAsync(true);
using var factory = _factory.WithWebHostBuilder(builder =>
{
builder.ConfigureServices(services =>
{
services.AddSingleton(fileUploaderMock.Object);
});
});
var client = factory.CreateClient();
var testFileContent = new StringContent("test data", Encoding.UTF8, "application/octet-stream");
// Act
var response = await client.PostAsync("/api/upload", testFileContent);
// Assert
fileUploaderMock.Verify(u => u.UploadAsync(It.IsAny<byte[]>()), Times.Once);
}
[Fact]
public async Task SendMail_Should_Call_MailSender()
{
// Arrange
var mailSenderMock = new Mock<IMailSender>();
mailSenderMock.Setup(m => m.SendAsync(It.IsAny<string>(), It.IsAny<string>())).ReturnsAsync(true);
using var factory = _factory.WithWebHostBuilder(builder =>
{
builder.ConfigureServices(services =>
{
services.AddSingleton(mailSenderMock.Object);
});
});
var client = factory.CreateClient();
var emailContent = new StringContent("{\"to\":\"test@example.com\", \"message\":\"Hello\"}", Encoding.UTF8, "application/json");
// Act
var response = await client.PostAsync("/api/sendmail", emailContent);
// Assert
mailSenderMock.Verify(m => m.SendAsync(It.IsAny<string>(), It.IsAny<string>()), Times.Once);
}
}
方法 | 特徴 |
---|---|
Factory内で一括モック | – すべてのテストで共通のモックを適用する場合に有効 |
テストごとに個別モック | – 各テストで異なる振る舞いを定義できる |
FactoryのDIコンテナを上書き | – WithWebHostBuilder を利用して、テスト単位でDIを変更 |
テストごとに異なるモックを適用することで、より柔軟なテストが可能!
モックの振る舞いをカスタマイズし、様々なケースを検証!
WebApplicationFactory
を使って結合テストHttpClient
を使い、エンドツーエンドのAPIテストWithWebHostBuilder
を利用し、個別ケースごとにモックを設定Moq
を利用して外部依存を排除し、振る舞いを検証IFileUploader.UploadAsync
の呼び出しを検証IMailSender.SendAsync
の呼び出しを検証これにより、テストごとに異なるモックを適用しながら、
Web API の振る舞いを正確に検証できるテストフレームワークを構築!