プロジェクトの品質向上を目的にユニットテストの導入が求められ、開発部門全体での実装体制構築を担当することになりました。
モックの必要性
ユニットテストにおけるモックの目的は「一度作成したテストコードがどの環境でも実行可能」にすることです。これによりDBや外部APIなどへの依存を排除し、テストの再現性と安定性を高めます。
モックツール比較
技術調査の結果、以下の選定となりました:
| ツール | 言語 | 特徴 | 選定理由 |
|---|---|---|---|
| Mockito | Java | Spring公式推奨 | Javaスタックとの親和性が高く柔軟なモック設定が可能 |
| MockServer | Java | HTTPリクエストシミュレーション | ネットワーク層のテストを簡易に実現 |
| Cobertura | Java | コードカバレッジ計測 | テスト網羅度の可視化が容易 |
他のツール(RAP2/EasyMock/WireMock/Postman)はJavaスタックとの親和性や設定の面で採用を見送りました。
Mockitoの使い方
基本構成
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>3.12.4</version>
<scope>test</scope>
</dependency>
Spring環境での実装例
@Mock
private SampleService mockService;
@BeforeEach
public void setUp() {
MockitoAnnotations.openMocks(this);
// モック挙動定義
when(mockService.processData(anyString()))
.thenAnswer(invocation -> {
String input = invocation.getArgument(0);
return "Processed: " + input;
});
}
Bean置換の代替手法
SampleService mock = Mockito.mock(SampleService.class,
(invocation) -> {
if ("calculate".equals(invocation.getMethod().getName())) {
return 100;
}
return null;
});
ReflectionTestUtils.setField(targetObject, "sampleService", mock);
MockServerの使い方
依存定義
<dependency>
<groupId>org.mock-server</groupId>
<artifactId>mockserver-netty</artifactId>
<version>5.15.0</version>
</dependency>
HTTPシミュレーション例
@BeforeEach
public void setupMockServer() {
mockServer = startClientAndServer(8089);
mockServer.when(
request()
.withPath("/api/v1/data")
.withMethod("POST")
.withHeader("Content-Type", "application/json")
).respond((request, responseBuilder) -> {
JSONObject body = new JSONObject(new String(request.getBody()));
if (!body.has("required_param")) {
return responseBuilder
.withStatusCode(400)
.withBody("{\"error\": \"missing required parameter\"}");
}
JSONObject result = new JSONObject();
result.put("status", "success");
result.put("data", body.get("input"));
return responseBuilder
.withBody(result.toString())
.withDelay(TimeUnit.SECONDS, 2); // 応答遅延シミュレーション
});
}
コードカバレッジ計測
Coberturaの設定
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<version>2.7</version>
<configuration>
<formats>
<format>html</format>
<format>xml</format>
</formats>
</configuration>
</plugin>
実行コマンド
mvn clean cobertura:cobertura
# 結果確認: target/site/cobertura/index.html
補足事項
- MockitoのSpy機能:実際のメソッド実行を維持しつつ一部挙動をモック化
- モックサーバーの動的レスポンス:リクエスト内容に基づく条件分岐処理
- テスト失敗時のログ出力強化:問題箇所の特定を迅速化