LoginSignup
5
2

mockito.MockedStatic を使うときの書き分け 2つ

Posted at

はじめに

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-inlinemockito-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しましょうね。

参考

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2