はじめに
mockedStatic
あんまり使ったことがなく、『エラーが何で起きてるか分からん!』と質問されたときに即答できなかったのが悔しかったので備忘。
もくじ
実行環境
- Java8 以降
- JUnit5
- Mockito 4.11.0
build.gradle
dependencies {
testImplementation('org.mockito:mockito-core:4.11.0')
testImplementation('org.mockito:mockito-inline:4.11.0') // 3.4.0以降でないと使えない
}
※ mockito-inline
は mockito-core
の機能を含んでいるため、mockito-inline
のみを追加しても問題ないようです
mockito.MockedStatic の書き方2つ
mockedStatic
は以下2通りの方法で書くことができます。
- メソッド参照
- ラムダ式
Javaのメソッド参照とラムダ式は Java 8
以降の機能になります。興味あったらそれぞれ詳しく調べてみてください。
サンプルコード
テスト対象クラス/メソッド
MyClassUtils.java
public class MyClassUtils {
// 引数なしのstaticメソッド
public static int staticMethodWithNoArguments() {
return 0;
}
// 引数ありのstaticメソッド
public static int staticMethodWithArguments(int input) {
return input;
}
メソッド参照を使う場合
MyClassUtilsTest.java
class MyClassUtilsTest {
@DisplayName("staticメソッド(引数なし)をmockStatic(メソッド参照)して100を返すように振る舞いを変える")
@Test
void mockStaticWithMethodReferenceTest() {
try (MockedStatic<MyClassUtils> mockedMyClassUtils = Mockito.mockStatic(MyClassUtils.class)) {
// Arrange
mockedMyClassUtils.when(MyClassUtils::staticMethodWithNoArguments).thenReturn(100);
// Act & Assert
assertThat(MyClassUtils.staticMethodWithNoArguments(), is(100));
}
}
@DisplayName("staticメソッド(引数あり)をmockStatic(メソッド参照)するとコンパイルエラーになる")
@Test
void compileError() {
try (MockedStatic<MyClassUtils> mockedMyClassUtils = Mockito.mockStatic(MyClassUtils.class)) {
// Arrange
mockedMyClassUtils.when(MyClassUtils::staticMethodWithArguments(2)).thenReturn(200);
// "Syntax error on token "staticMethodWithArguments", AssignmentOperator expected after this token"
// Act & Assert
assertThat(MyClassUtils.staticMethodWithArguments(2), is(200));
}
}
}
ラムダ式を使う場合
MyClassUtilsTest.java
class MyClassUtilsTest {
@DisplayName("staticメソッド(引数なし)をmockStatic(ラムダ式)して300を返すように振る舞いを変える")
@Test
void mockStaticWithLambdaExpressionTest() {
try (MockedStatic<MyClassUtils> mockedMyClassUtils = Mockito.mockStatic(MyClassUtils.class)) {
// Arrange
mockedMyClassUtils.when(() -> MyClassUtils.staticMethodWithNoArguments()).thenReturn(300);
// Act & Assert
assertThat(MyClassUtils.staticMethodWithNoArguments(), is(300));
}
}
@DisplayName("staticメソッド(引数あり)をmockStatic(ラムダ式)して400を返すように振る舞いを変える")
@Test
void mockStaticWithLambdaExpressionTest2() {
try (MockedStatic<MyClassUtils> mockedMyClassUtils = Mockito.mockStatic(MyClassUtils.class)) {
// Arrange
mockedMyClassUtils.when(() -> MyClassUtils.staticMethodWithArguments(4)).thenReturn(400);
// Act & Assert
assertThat(MyClassUtils.staticMethodWithArguments(4), is(400));
}
}
}
使い分け
モックしたいメソッドに引数があるかどうかで判断することが1つの方法。
- 単純にメソッドを指定するだけならメソッド参照(シンプルで読みやすい記法)
- 引数に対して何らかの操作や条件分岐が必要ならラムダ式(より複雑な動作に対応できる記法)
注意:サンプルコードのように try-with-resources
を使わないで mockedStatic
使う場合は必ずcloseしましょうね。
参考