本記事は NECソリューションイノベータ Advent Calendar 2021 の 12/20 の記事です。
こんにちは。
先日 Spring Boot を 2.5.3 から 2.6.1 にバージョンアップする機会があったのですが、単体テストが通らなくなって困った話をします。
テストが通らねぇ・・・
Spring Bootをバージョンアップして mvn clean test
とすると・・・。
むむむ・・・。
java.lang.NoSuchMethodError: org.mockito.Answers.get()Lorg/mockito/stubbing/Answer;
at org.powermock.api.extension.listener.AnnotationEnabler.standardInject(AnnotationEnabler.java:85)
at org.powermock.api.extension.listener.AnnotationEnabler.beforeTestMethod(AnnotationEnabler.java:55)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
これは謎・・・。
ぐーぐる先生に聞いてみよう
ぐーぐる先生に頼ります。
私は結構(いやかなり)横着なので、エラー内容をそのままコピペして検索しちゃいますw
ふむふむ・・・✧φ(ロ-ロ๑)
GitHub に Issue が上がってました。
Mockito のバージョンが上がったことで PowerMock との互換性がなくなったみたいですね。
バージョンダウンもワークアラウンドとしてあるようですが、これまで PowerMock に頼っていた静的メソッドのモッキングがMockitoでもできるようになったということで、せっかくなのでこれを試してみようと思います。
いざ実践
これを・・・
@RunWith(PowerMockRunner.class)
@PrepareForTest({ ClassA.class })
public class staticTest {
@Test
public void test() {
PowerMockito.mockStatic(ClassA.class);
when(ClassA.methodStatic()).thenReturn("OK!!");
// 以下略
}
}
こう書き換えます。
public class staticTest {
@Test
public void test() {
try (MockStatic<ClassA> mocked = Mockito.mockStatic(ClassA.class)) {
mocked.when(() -> ClassA.methodStatic()).thenReturn("OK!!");
// 以下略
}
}
}
try
で囲まずに最後にモックをクローズ(この例でいうと mocked.close()
)する記法もあるのですが、 try
で囲むとスコープが限定されてわかりやすいですし、クローズ漏れもなくなるのでこの記法を採用しました。
で、再テスト。
[INFO] Results:
[INFO]
[INFO] Tests run: 171, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 01:04 min
[INFO] Finished at: 2021-12-xxTHH:mm:ss+09:00
[INFO] ------------------------------------------------------------------------
テストをパスしました!
まとめ
Spring Bootってマイナー以上のバージョンを上げるとき、テストフレームワーク起因の非互換が発生することがちょいちょいあるんですよね。
これからもバージョンを上げるときは覚悟して挑みたいと思います(笑)