🍃

【JUnit 5】静的メソッドのMock利用【Mockito】

2024/03/05に公開

記事背景

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();で必ず閉じる必要があるそうです。↓(参考)
https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/MockedStatic.html

まとめ

Spring bootで単体テストを始めたばかりの時、躓いたところでした。
過去に困った箇所だったので、記事にしておきます。

Discussion