【Java】mockitoでstaticメソッドをモックする方法
投稿 2026年3月21日
最終更新 2026年3月21日
専門用語多め
前置き
レガシーコードを触る機会がありリファクタリングしたいのはやまやまですが、リターンよりリスクのほうが高すぎるので、まずはテストコードを書こうと思いました。
その時にstaticメソッドをモックする必要があったので、その備忘録です。
前提
依存関係
JUnitとmockitoを使います。
dependencies {
implementation(platform("org.junit:junit-bom:5.10.2"))
testImplementation("org.junit.jupiter:junit-jupiter")
testImplementation("org.mockito:mockito-junit-jupiter:5.11.0")
testImplementation("org.mockito:mockito-inline:5.2.0")
}
JUnit5を使い、staticメソッドをモックをするためにmockito-inlineを入れます。
パターン
今回は下記4パターンのstaticメソッドをモックします。
| クラス名 | メソッド名 | 引数 | 戻り値 |
|---|---|---|---|
| LegacyUtils | noArgsVoid | - | - |
| LegacyUtils | argsVoid | ● | - |
| LegacyUtils | noArgsReturn | - | ● |
| LegacyUtils | argsReturn | ● | ● |
テスト対象クラス
staticメソッドを呼び出すテスト対象のメソッドです。
public class LegacyService {
public void noArgsVoid() {
LegacyUtils.noArgsVoid();
}
public void argsVoid() {
LegacyUtils.argsVoid("123", "test");
}
public String noArgsReturn() {
return LegacyUtils.noArgsReturn();
}
public String argsReturn() {
return LegacyUtils.argsReturn("123", "test");
}
}
モックするstaticメソッド
今回モックするstaticメソッドです。
実際に実行してしまうと例外が出る体で、実行時エラーを投げます。
これによりモックされており、中身が実行されていないかがわかります。
public class LegacyUtils {
public static void noArgsVoid() {
throw new RuntimeException();
}
public static void argsVoid(String id, String name) {
throw new RuntimeException();
}
public static String noArgsReturn() {
throw new RuntimeException();
}
public static String argsReturn(String id, String name) {
throw new RuntimeException();
}
}
テストコード
これから紹介するテストコードは、下記クラスに記載していきます。
@ExtendWith(MockitoExtension.class)
class LegacyServiceTest {
@InjectMocks
private LegacyService legacyService;
// テストコードを記載
}
staticモックをするためにMockitoExtensionを使います。
引数なし戻り値なしstaticメソッドをモック
@Test
void モックしないと実体が実行され例外が投げられる() {
// when&then
assertThrows(RuntimeException.class, () -> legacyService.noArgsVoid());
}
@Test
void mockStaticを行うだけで実体は実行されない() {
try (MockedStatic<LegacyUtils> mockLegacyUtils = mockStatic(LegacyUtils.class)) {
// when&then
assertDoesNotThrow(() -> legacyService.noArgsVoid());
}
}
@Test
void 何もしないことを明示的にモック() {
try (MockedStatic<LegacyUtils> mockLegacyUtils = mockStatic(LegacyUtils.class)) {
// given
mockLegacyUtils.when(LegacyUtils::noArgsVoid).thenAnswer(i -> null);
// when&then
assertDoesNotThrow(() -> legacyService.noArgsVoid());
}
}
引数あり戻り値なしstaticメソッドをモック
@Test
void モックしないと実体が実行され例外が投げられる() {
// when&then
assertThrows(RuntimeException.class, () -> legacyService.argsVoid());
}
@Test
void mockStaticを行うだけで実体は実行されない() {
try (MockedStatic<LegacyUtils> mockLegacyUtils = mockStatic(LegacyUtils.class)) {
// when&then
assertDoesNotThrow(() -> legacyService.argsVoid());
}
}
@Test
void 何もしないことを明示的にモック() {
try (MockedStatic<LegacyUtils> mockLegacyUtils = mockStatic(LegacyUtils.class)) {
// given
String id = anyString();
String name = anyString();
mockLegacyUtils.when(() -> LegacyUtils.argsVoid(id, name)).thenAnswer(i -> null);
// when&then
assertDoesNotThrow(() -> legacyService.argsVoid());
}
}
引数なし戻り値ありstaticメソッドをモック
@Test
void モックしないと実体が実行され例外が投げられる() {
// when&then
assertThrows(RuntimeException.class, () -> legacyService.noArgsReturn());
}
@Test
void mockStaticを行うだけで実体は実行されない() {
try (MockedStatic<LegacyUtils> mockLegacyUtils = mockStatic(LegacyUtils.class)) {
// when
String result = legacyService.noArgsReturn();
// then
assertNull(result);
}
}
@Test
void 戻り値を明示的にモック() {
try (MockedStatic<LegacyUtils> mockLegacyUtils = mockStatic(LegacyUtils.class)) {
// given
mockLegacyUtils.when(LegacyUtils::noArgsReturn).thenReturn("success");
// when
String result = legacyService.noArgsReturn();
// then
assertEquals("success", result);
}
}
引数あり戻り値ありstaticメソッドをモック
@Test
void モックしないと実体が実行され例外が投げられる() {
// when&then
assertThrows(RuntimeException.class, () -> legacyService.argsReturn());
}
@Test
void mockStaticを行うだけで実体は実行されない() {
try (MockedStatic<LegacyUtils> mockLegacyUtils = mockStatic(LegacyUtils.class)) {
// when
String result = legacyService.argsReturn();
// then
assertNull(result);
}
}
@Test
void 戻り値を明示的にモック() {
try (MockedStatic<LegacyUtils> mockLegacyUtils = mockStatic(LegacyUtils.class)) {
// given
String id = anyString();
String name = anyString();
mockLegacyUtils.when(() -> LegacyUtils.argsReturn(id, name)).thenReturn("success");
// when
String result = legacyService.argsReturn();
// then
assertEquals("success", result);
}
}
まとめ
レガシーコードのリファクタリングやテストコードは骨が折れます…。
でも手を動かさないことには一向に状況は変わらないので、頑張ってテストコード書いていこうと思います。
本音ではちょっとあきらめてましたが、mockitoのおかげで無事テストが書けて良かったです。
以上、ここまで見ていただきありがとうございます。
皆さまの快適な開発ライフに、ほんの少しでもお役に立てれば幸いです。