1. ホーム
  2. java

[解決済み】@Mock、@MockBean、Mockito.mock()の違いについて)

2022-04-12 07:28:21

質問

テストを作成し、依存関係をモック化する場合、この3つのアプローチの違いは何でしょうか?

  1. MockBeanを使用します。

    @MockBean
    MyService myservice;
    
    
  2. モック(@Mock)です。

    @Mock
    MyService myservice;
    
    
  3. モッキート.モック()

    MyService myservice = Mockito.mock(MyService.class);
    
    

解決方法は?

プレーンなMockitoライブラリ

import org.mockito.Mock;
...
@Mock
MyService myservice;

そして

import org.mockito.Mockito;
...
MyService myservice = Mockito.mock(MyService.class);

はMockitoライブラリから提供されており、機能的に同等です。

これらは、クラスやインターフェースをモックし、その動作を記録・検証することができます。

アノテーションを使用する方法は、短時間で済むので、好ましいし、しばしば好まれる。


なお、テスト実行時にMockitoのアノテーションを有効にするために MockitoAnnotations.initMocks(this) 静的メソッドを呼び出す必要があります。

テスト間の副作用を避けるために、各テスト実行の前に行うことをお勧めします。

@Before 
public void initMocks() {
    MockitoAnnotations.initMocks(this);
}

Mockitoのアノテーションを有効にするもう1つの方法は、テスト・クラスに対して @RunWith を指定することで MockitoJUnitRunner このタスクを実行し、また他の有用なことを行う :

@RunWith(org.mockito.runners.MockitoJUnitRunner.class)
public MyClassTest{...}


MockitoライブラリをラッピングするSpring Bootライブラリ

これはまさに Spring Bootクラス :

import org.springframework.boot.test.mock.mockito.MockBean;
...
@MockBean
MyService myservice;

このクラスは spring-boot-test ライブラリを使用します。

これは、MockitoのモックをSpringの ApplicationContext .

宣言されたクラスと互換性のあるBeanがコンテキストに存在する場合,それは を置き換えます。 をモックに置き換えます。

そうでない場合、それは が追加されます。 をビーンとしてコンテキストに追加します。

Javadocリファレンス。

<ブロッククオート

モックをSpringに追加するために使用できるアノテーションです。 ApplicationContext。

...

コンテキストに定義された同じ型の既存の単一Beanがある場合 はモックで置き換えられ、既存のビーンが定義されていない場合は、新しいビーンが定義されます。 が追加されます。


クラシック/プレーンMockitoを使用する場合と @MockBean Spring Bootから?

ユニットテストは、あるコンポーネントを他のコンポーネントから分離してテストするために設計されています。また、ユニットテストには、開発者のマシンで毎日何十回も実行される可能性があるため、実行時間の点で可能な限り高速であるという要件があります。

そこで、簡単なガイドラインを示します。

Spring Bootコンテナからの依存を必要としないテストを書く場合、クラシック/プレーンMockitoは、従うべき方法です。

テストがSpring Bootコンテナに依存する必要がある場合 を使用する場合は、 コンテナ Bean のひとつを追加したりモックにしたりする必要があります。 @MockBean をSpring Bootから取得する方法があります。


Spring Bootの代表的な使い方 @MockBean

でアノテーションされたテストクラスを作成します。 @WebMvcTest (ウェブテストスライス)。

Spring Bootのドキュメント は、そのことを非常によくまとめています。

よくあること @WebMvcTest は1つのコントローラに限定して使用されます。 との組み合わせで @MockBean のモック実装を提供する。 が必要な共同作業者です。

以下はその例です。

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

@RunWith(SpringRunner.class)
@WebMvcTest(FooController.class)
public class FooControllerTest {

    @Autowired
    private MockMvc mvc;

    @MockBean
    private FooService fooServiceMock;

    @Test
    public void testExample() throws Exception {
         Foo mockedFoo = new Foo("one", "two");

         Mockito.when(fooServiceMock.get(1))
                .thenReturn(mockedFoo);

         mvc.perform(get("foos/1")
            .accept(MediaType.TEXT_PLAIN))
            .andExpect(status().isOk())
            .andExpect(content().string("one two"));
    }

}