🍃
【JUnit 5】静的メソッドのMock利用【Mockito】
記事背景
Spring Boot + JUnit(+Mockito)で単体テストを実行した際、下記エラーが出ました。
java.lang.illegalstateexception failed to load applicationcontext
caused by org.springframework.beans.factory.beancreationexception : error creating bean with name 'java.nio.file.files' : instantiation of bean failed
1行目にアプリケーションのコンテキストのロードに失敗したと書かれています。
2行目に原因がBeanを作成しようとした際に例外が発生し、具体的にはjava.nio.file.FilesのBeanのインスタンス化に失敗したと書かれています。
上記エラーは、テストメソッドの内容に問題があるわけではありません。
エラーの原因は、java.nio.file.FilesのクラスをMock化する際、下記のような定義を行いました。
@MockBean
Files files;
java.nio.file.Files は静的メソッドを提供するユーティリティクラスです。
ユーティリティクラスは、インスタンス化せず、直接クラス名を使用してメソッドを呼び出します。
そのため、Beanとして定義することができません。
では上記のようなクラスをMock化するのかという話です。
静的メソッドのMock化方法
以下のような書き方で静的メソッドをMock化することができます。
@Test
public void staticMethodMock() {
try (MockedStatic<ClassName> mockedStatic = Mockito.mockStatic(ClassName.class)) {
mockedStatic.when(() -> ClassName.staticMethodName("引数")).thenReturn("期待値");
}
}
エラーパターンを作りたい場合、下記です。
@Test
public void staticMethodMock() {
try (MockedStatic<ClassName> mockedStatic = Mockito.mockStatic(ClassName.class)) {
mockedStatic.when(() -> ClassName.staticMethodName("引数")).thenThrow(new Exception("エラー期待値"));
}
}
この方法を使うことで、静的メソッドをMockにできます。
注意点は、上記はtry-with-resources文で書いていますが、それ以外の場合は処理終了時にmockedStatic.close();で必ず閉じる必要があるそうです。↓(参考)
まとめ
Spring bootで単体テストを始めたばかりの時、躓いたところでした。
過去に困った箇所だったので、記事にしておきます。
Discussion