Spring Boot 3.4へ上げたら、これまで当たり前に使っていた @MockBean に取り消し線が引かれて非推奨警告が出た、という方は多いと思います。テスト記事でも散々使ってきたアノテーションなので、いきなり deprecated 扱いされると戸惑いますよね。

結論から言うと、置き換え先は @MockitoBean@MockitoSpyBean です。この記事では、正しいimportとパッケージの変更点、旧APIとの差分、そして既存テストをまとめて機械的に移行する手順を整理します。

なぜSpring Boot 3.4で@MockBeanが非推奨になったのか

@MockBean@SpyBean は、Spring Boot 3.4で @Deprecated になりました。理由はシンプルで、これまでBoot独自の実装だったモック注入の仕組みが、Spring Framework 6.2で導入された Bean Override という標準機構に統合されたからです。

つまり「Boot固有の便利機能」だったものが、「Framework標準のテスト機能」へと役割ごと移動した、というのが今回の流れです。Bean Override は Mockito 以外の差し替えにも使える汎用的な仕組みで、その一部として Mockito 用のアノテーションが用意されました。

大事なのは、非推奨になっただけで まだ動く という点です。3.4に上げた瞬間に既存テストが赤くなるわけではありません。警告が出るだけなので、慌てず計画的に移行すれば大丈夫です。

置き換え先アノテーションとパッケージの対応

何を何に置き換えるのか、まず対応を押さえましょう。アノテーション名だけでなく importパッケージも変わる のがポイントです。

旧 (非推奨)
@MockBean@MockitoBean
@SpyBean@MockitoSpyBean

パッケージはこう変わります。

// 旧: Spring Boot 側
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.boot.test.mock.mockito.SpyBean;

// 新: Spring Framework 側
import org.springframework.test.context.bean.override.mockito.MockitoBean;
import org.springframework.test.context.bean.override.mockito.MockitoSpyBean;

boot.test.mock.mockito から test.context.bean.override.mockito へと、パッケージがまるごと移動しています。アノテーション名を変えるだけだとimportが解決できずコンパイルエラーになるので、両方セットで直す必要があります。

@MockitoBeanの基本的な使い方

@WebMvcTest でコントローラをテストし、依存する Service をモック化する典型パターンで見てみます。まずは旧コードです。

@WebMvcTest(UserController.class)
class UserControllerTest {

    @Autowired
    MockMvc mockMvc;

    @MockBean
    UserService userService;

    @Test
    void getUser() throws Exception {
        when(userService.findById(1L))
            .thenReturn(new User(1L, "Alice"));

        mockMvc.perform(get("/users/1"))
            .andExpect(status().isOk());
    }
}

これを @MockitoBean に置き換えると、変わるのはアノテーションとimportだけです。

import org.springframework.test.context.bean.override.mockito.MockitoBean;

@WebMvcTest(UserController.class)
class UserControllerTest {

    @Autowired
    MockMvc mockMvc;

    @MockitoBean
    UserService userService;

    // when(...) や verify(...) の書き方はそのまま
}

注目してほしいのは、whenverify といった Mockito 側の書き方は 一切変わらない という点です。あくまでBeanを差し替える入り口のアノテーションが変わっただけなので、テスト本体のロジックはそのまま使えます。MockMvc テスト自体の書き方は Spring BootのMockMvcでコントローラをテストする方法 にまとめているので、あわせてどうぞ。

@MockitoSpyBeanの使い方

スパイ、つまり実装を呼びつつ一部だけスタブしたい場合は @SpyBean を使っていたはずです。こちらも同じ要領で @MockitoSpyBean に置き換えます。

import org.springframework.test.context.bean.override.mockito.MockitoSpyBean;

@SpringBootTest
class OrderServiceTest {

    @MockitoSpyBean
    NotificationService notificationService;

    @Test
    void placeOrder() {
        // 実装は呼びつつ、一部メソッドだけ差し替える
        doNothing().when(notificationService).notify(any());
        // ...
    }
}

部分モックの挙動、つまり明示的にスタブしたメソッド以外は実装がそのまま呼ばれる、という性質も維持されます。@DataJpaTest などの別スライスで使っている場合も方針は同じで、アノテーションとimportを差し替えるだけです。スライステスト自体の詳細は @DataJpaTestでリポジトリをスライステストする方法 を参照してください。

@MockBeanとの差分と移行時の注意点

ほとんどのケースはアノテーション名の置き換えで済みますが、Bean特定のルールは意識しておくと安心です。

@MockitoBean はフィールドの型を使って対象のBeanを解決します。同じ型のBeanが1つだけならそのまま差し替わりますが、同じ型の候補が複数ある 場合は、どれを差し替えるか曖昧になります。その場合は name 属性で対象を明示しましょう。

@MockitoBean(name = "primaryUserService")
UserService userService;

このあたりの解決ルールは旧 @MockBean の考え方と大きくは変わりませんが、複数候補があるテストを移行するときは、置き換え後に対象が意図どおり差し替わっているかを確認しておくと安全です。細かなバージョン依存の挙動差については、断定せず公式リファレンスで最新の仕様を確認することをおすすめします。

既存テストを一括移行する手順

テストクラスが何十個もあると、手で直すのは現実的ではありません。grep で洗い出して sed でまとめて置換しましょう。まずは対象箇所の確認からです。

grep -rn "MockBean\|SpyBean" src/test/java

件数と場所を把握したら、import とアノテーション名を一括で置き換えます。順番として、パッケージの長い import 行から先に処理すると安全です。

# import 行を先に置換
grep -rl "org.springframework.boot.test.mock.mockito.SpyBean" src/test/java \
  | xargs sed -i 's#org.springframework.boot.test.mock.mockito.SpyBean#org.springframework.test.context.bean.override.mockito.MockitoSpyBean#g'

grep -rl "org.springframework.boot.test.mock.mockito.MockBean" src/test/java \
  | xargs sed -i 's#org.springframework.boot.test.mock.mockito.MockBean#org.springframework.test.context.bean.override.mockito.MockitoBean#g'

# アノテーション名を置換 (SpyBean を先に)
grep -rl "@SpyBean" src/test/java | xargs sed -i 's/@SpyBean/@MockitoSpyBean/g'
grep -rl "@MockBean" src/test/java | xargs sed -i 's/@MockBean/@MockitoBean/g'

@SpyBean@MockBean より先に処理しているのは、単純置換で Spy が巻き込まれないようにするためです。置換が終わったらコンパイルし、未使用importが残っていないか確認します。IDE のインポート整理機能を使うと楽ですね。

最後に、必ずテストを実行してグリーンを確認しましょう。機械的な置換なので基本は通りますが、前述の複数候補ケースだけは挙動が変わる可能性があるので、ここで拾えます。

./gradlew test

非推奨のまま残すとどうなるか

「動くなら放置でいいのでは」と思うかもしれませんが、非推奨APIは将来のメジャーバージョンで削除される可能性があります。そのタイミングでアップグレードすると、今度は警告ではなくコンパイルエラーとして一気に降りかかってきます。

また、非推奨警告が大量に出続けるとビルドログのノイズになり、本当に見るべき警告が埋もれてしまいます。技術的負債として静かに溜まっていくので、あまり気持ちのいい状態ではありません。

現実的には、Spring Boot のアップグレード作業とセットで一括移行してしまうのがおすすめです。今回紹介した grep/sed の手順なら数分で終わりますし、テスト全体の書き方を見直すきっかけにもなります。Spring Boot 2から3への移行全般については Spring Boot 2から3へのアップグレードガイド にまとめているので、あわせて計画してみてください。

まとめ

@MockBean の非推奨化は、Boot独自機能がFramework標準のBean Overrideに統合された自然な流れです。やることはシンプルで、@MockitoBean / @MockitoSpyBean へアノテーションとimportを差し替えるだけ。Mockito の書き方自体は変わりません。grep と sed でまとめて移行し、テストがグリーンなのを確認すれば完了です。警告が出ているうちに、さっと片付けてしまいましょう。