【概要】
モック対象にfinal修飾子があるとモックにならない場合があります。
具体的なコードで説明していきます。
【環境】
Java 11
JUnit 5.10.0
Mockito 5.5.0
【コード】
下記コードは上記GitHubにアップロードしているコードと同じです。
本コードでのモック対象はHogeクラスのhugaフィールドとなります。
Hoge.java
package org.example;
public class Hoge {
private Huga huga;
// final修飾子を付けるとテスト失敗する
// private final Huga huga;
private final Piyo piyo;
public Hoge(final Huga huga, final Piyo piyo) {
this.huga = huga;
this.piyo = piyo;
}
public String hoge() {
return huga.huga() + piyo.piyo();
}
}
Huga.java
package org.example;
public class Huga {
public String huga() {
return "huga";
}
}
Piyo.java
package org.example;
public class Piyo {
public String piyo() {
return "piyo";
}
}
HogeTest.java
package org.example;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.doReturn;
public class HogeTest {
private AutoCloseable closeable;
@InjectMocks
private Hoge hoge = new Hoge(new Huga(), new Piyo());
@Mock
private Huga huga;
@BeforeEach
void setUp() {
closeable = MockitoAnnotations.openMocks(this);
}
@AfterEach
void tearDown() throws Exception {
closeable.close();
}
@Test
void 文字列が連結されていること() {
doReturn("test").when(huga).huga();
assertEquals("testpiyo", hoge.hoge());
}
}
【テスト結果】
final修飾子がない場合
GitHubにアップロードされているコードのままだと、テスト成功します。
final修飾子がある場合
下記のようにfinal修飾子がある宣言の方をコメントアウトしてからテスト実行すると、テスト失敗します。
Hoge.javaの一部抜粋
// private Huga huga;
// final修飾子を付けるとテスト失敗する
private final Huga huga;
private final Piyo piyo;
エラーメッセージ
org.opentest4j.AssertionFailedError:
予想:testpiyo
実際:hugapiyo
<クリックで差分を表示>
at org.junit.jupiter.api.AssertionFailureBuilder.build(AssertionFailureBuilder.java:151)
at org.junit.jupiter.api.AssertionFailureBuilder.buildAndThrow(AssertionFailureBuilder.java:132)
at org.junit.jupiter.api.AssertEquals.failNotEqual(AssertEquals.java:197)
at org.junit.jupiter.api.AssertEquals.assertEquals(AssertEquals.java:182)
at org.junit.jupiter.api.AssertEquals.assertEquals(AssertEquals.java:177)
at org.junit.jupiter.api.Assertions.assertEquals(Assertions.java:1141)
at org.example.HogeTest.文字列が連結されていること(HogeTest.java:34)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
プロセスは終了コード -1 で終了しました
【なぜfinal修飾子があるとテスト失敗するのか考察】
テスト実行の流れ
①private Hoge hoge = new Hoge(new Huga(), new Piyo());
のnew Huga()
によってインスタンスがhuga
変数に設定される。
②final修飾子により再代入することができないため、huga
変数はモックにはなれない。
テスト失敗結果に「実際:hugapiyo」と出力されているので、new Huga()
のインスタンスを使っておりモックで設定した返却値を使わないのでテスト失敗します。