@ Mock、@ MockBean、Mockito.mock()の違い


147

テストを作成して依存関係を模擬する場合、これらの3つのアプローチの違いは何ですか?

  1. @MockBean:

    @MockBean
    MyService myservice;
  2. @モック:

    @Mock
    MyService myservice;
  3. Mockito.mock()

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

回答:


198

プレーンな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アノテーションを有効にする別の方法は、このタスクを実行@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がコンテキスト内に存在する場合は、モックに置き換えられます。
そうでない場合、モックをBeanとしてコンテキストに追加します。

Javadocリファレンス:

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

...

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


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

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

したがって、ここに簡単なガイドラインがあります:

Spring Bootコンテナからの依存関係を必要としないテストを作成する場合、クラシック/プレーンのMockitoが従う方法です。高速であり、テストされるコンポーネントの分離を優先します。
あなたのテストでは、春のブートコンテナに依存する必要がある場合、あなたはまた、コンテナ豆の1を追加したり、モックたい:@MockBean春のブートからの方法です。


Spring Bootの典型的な使用法 @MockBean

@WebMvcTest(Webテストスライス)で注釈が付けられたテストクラスを記述します。

Spring Bootドキュメントはそれを非常にうまくまとめています:

多くの場合@WebMvcTest、単一のコントローラーに限定され、と組み合わせて使用​​して@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"));
    }

}

4
@MockBeanを使用すると、Beanのコピーが作成され、ApplicationContextに挿入されますか?または、モックBeanのメソッドはすべてnullになりますか?すべてのメソッドがnullの場合、@ Mockを使用する場合と同じようにスタブ化できますか?
ダグ

6
説明したように、@MockBean同じタイプを宣言するBeanがSpring構成ですでに定義されている場合、using はアプリケーションコンテキストのBeanを置き換えます。そして、@MockBean.DIメカニズムがこのように機能することを宣言するクラスで注入が実行されます 。DIコンテキストでオブジェクトを登録し、特定のクラスのSpringコンテキストで参照されるオブジェクトを注入できます。DIコンテキストでオブジェクトを注入しません。
davidxxx

13

最後に説明するのは簡単です。アノテーションのjavadocsを調べるだけで、違いがわかります。

@モック:(org.mockito.Mock

フィールドをモックとしてマークします。

  • 簡略なモック作成を許可します。
  • 反復的なモック作成コードを最小化します。
  • テストクラスを読みやすくします。
  • フィールド名はモックの識別に使用されるため、検証エラーが読みやすくなります。

@MockBean:(org.springframework.boot.test.mock.mockito.MockBean

Spring ApplicationContextにモックを追加するために使用できるアノテーション。クラスレベルのアノテーションとして@Configuration、またはクラスのフィールド、または@RunWithSpringRunnerであるテストクラスで使用できます。

モックはタイプまたはBean名で登録できます。コンテキストで定義された同じタイプの既存の単一のBeanはモックに置き換えられます。既存のBeanが定義されていない場合は、新しいものが追加されます。

場合@MockBean分野で使用され、ならびにアプリケーション・コンテキストに登録され、模擬は、フィールド内に注入されます。

Mockito.mock()

その単なる表現です@Mock


5
@MockではMockitoRunnerまたはinitMocksを手動で呼び出す必要があることを忘れないでください。
Florian Schaetz

4
唯一の違いである@MockBean@Mock1がにモックを注入することSpring ApplicationContextや、他の意志ではありませんか?
Doug

3
@DougあなたはMockBeanは春ブーツの一部であることを覚えておくだけでなく、それをまとめたが、1人のニーズ
comiventor
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.