web-dev-qa-db-ja.com

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

テストを作成し依存関係をあざけるとき、これら3つのアプローチの違いは何ですか?

  1. @MockBean:

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

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

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

Plain Mockito library

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つの方法は、このタスクを実行するMockitoJUnitRunnerを指定してテストクラスに@RunWithでアノテーションを付けることです。

@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がコンテキスト内に存在する場合、それはreplace itをモックで置き換えます。
そうでない場合は、Beanとしてコンテキスト内のモックを追加します。

Javadocのリファレンス:

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

...

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


いつでもclassic/plain Mockitoを使っていて、Spring Bootの@MockBeanを使っていますか?

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

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

Spring Bootコンテナからの依存関係を必要としないテストを書くときは、古典的な/普通のMockitoが従うべき方法です:それは速く、テストされたコンポーネントの分離を支持します。
あなたのテストがSpring Bootコンテナに頼る必要がある場合andあなたはコンテナBeanの1つを追加するか、またはモックしたいと思います:Spring Bootからの@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"));
    }

}
124
davidxxx

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

@モック:(org.mockito.Mock

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

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

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

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

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

アプリケーションコンテキストに登録されているだけでなく、フィールドで@MockBeanが使用されている場合、モックもフィールドに挿入されます。

Mockito.mock()

それは@Mockの単なる表現です。

7
Patrick