SpringBootTestでMockMvcを使用する場合とWebMvcTestを使用する場合の違い


98

私はSpringBootを初めて使用し、SpringBootでテストがどのように機能するかを理解しようとしています。次の2つのコードスニペットの違いについて少し混乱しています。

コードスニペット1:

@RunWith(SpringRunner.class)
@WebMvcTest(HelloController.class)
public class HelloControllerApplicationTest {
    @Autowired    
    private MockMvc mvc;

    @Test
    public void getHello() throws Exception {
        mvc.perform(MockMvcRequestBuilders.get("/").accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk())
                .andExpect(content().string(equalTo("Greetings from Spring Boot!")));
    }
}

このテストでは、@WebMvcTestフィーチャスライステスト用であると私が信じているアノテーションを使用し、WebアプリケーションのMVCレイヤーのみをテストします。

コードスニペット2:

@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class HelloControllerTest {

    @Autowired
    private MockMvc mvc;

    @Test
    public void getHello() throws Exception {
    mvc.perform(MockMvcRequestBuilders.get("/").accept(MediaType.APPLICATION_JSON))
            .andExpect(status().isOk())
            .andExpect(content().string(equalTo("Greetings from Spring Boot!")));
    }
}

このテストでは、@SpringBootTestアノテーションとを使用しMockMvcます。では、これはコードスニペット1とどう違うのですか?これは何が違うのですか?

編集:コードスニペット3の追加(これはSpringドキュメントの統合テストの例として見つかりました)

@RunWith(SpringRunner.class) 
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) 
public class HelloControllerIT {
    
    @LocalServerPort private int port;
    private URL base;
    
    @Autowired private TestRestTemplate template;
    
    @Before public void setUp() throws Exception {
        this.base = new URL("http://localhost:" + port + "/");
    }
    
    @Test public void getHello() throws Exception {
        ResponseEntity < String > response = template.getForEntity(base.toString(), String.class);
        assertThat(response.getBody(), equalTo("Greetings from Spring Boot!"));
    }
}

回答:


88

@SpringBootTest一般的なテストアノテーションです。1.4より前のバージョンと同じことを行うものを探している場合は、それを使用する必要があります。スライスはまったく使用されません。つまり、アプリケーションコンテキスト全体が開始され、コンポーネントのスキャンはまったくカスタマイズされません。

@WebMvcTest定義したコントローラーとMVCインフラストラクチャのみをスキャンします。それでおしまい。したがって、コントローラーがサービスレイヤーからの他のBeanに依存している場合、その構成を自分でロードするか、モックを提供するまで、テストは開始されません。アプリのごく一部しか読み込まないため、これははるかに高速です。この注釈はスライスを使用します。

ドキュメント読むこともおそらくあなたを助けるはずです。


返信ありがとうございます!!。したがって、私があなたを正しく理解している場合、それは、両方のコードスニペットがアプリケーションのMVC部分のみをテストすることを意味します。ただし、tcodeスニペット1は完全なアプリケーションコンテキストをロードしますが、コードスニペット2はコントローラーのみをスキャンします。これは正しいです?コードスニペット1は、コントローラーをテストするための単体テストと見なすことができますか?
Revansha 2016年

1
いいえ、それは正しくありません。SpringBootTestは完全なアプリを読み込んでいます(ある程度、利用可能なものwebEnvironmentがある場合、デフォルトでは埋め込みコンテナーを開始しません。それが目的です)。これは@SpringBootTestコントローラーの単体テストではなく、実際には統合テストであるとは言えません。WebMvcTest依存関係がある場合は、自分でコントローラーを提供する必要があるという意味で、実際にはコントローラーの単体テストです(構成または何らかのモックのいずれか)。
ステファンニコル2016年

返信ありがとうございます。質問を編集し、コードスニペット3を追加しました。統合テストでは@SpringBootTestアノテーションがより多く使用されるとおっしゃいました。Snippet3がこれを示していると思います。では、統合テストがスニペット3のように行われる場合、スニペット2は何をしますか?Snippet 2は、SpringBootTestアノテーションとモック環境(wenEnvironment属性のデフォルト値)を使用します。また、スニペット3は組み込みサーバーを起動し、実際にHTTP呼び出しを行いますが、スニペット2はこれを行いません。それで、これを考慮すると、スニペット2は単体テストと見なされませんか?
Revansha 2016年

4
ここでこれを整理するかどうかはわかりません。多分キラキラ?常に見逃しているように思われるのはSpringBootTestWebMvcTest作成するアプリケーションコンテキストが大幅に異なることです。前者はアプリ全体をロードしてすべての自動構成を有効にしますが、後者はSpring Mvcのみを有効にし、以外はスキャンしませんHelloController。結局のところ、それはすべて、ユニットテストの意味によって異なります。しかし、それが違いです。
ステファンニコル2016年

お返事をありがとうございます。それは私にとって非常に役に立ちます。これで、SpringBootTestでテストを実行できる理由がわかりましたが、WebMvcTestでは例外が発生します。どうもありがとうございました。
Alps19 9220年

71

@SpringBootTestアノテーションは、Spring Bootにメインの構成クラス(たとえば@SpringBootApplicationを持つクラス)を探し、それを使用してSpringアプリケーションコンテキストを開始するように指示します。SpringBootTestは完全なアプリケーションをロードし、遅くなる可能性のあるすべてのBeanを注入します。

@ WebMvcTest-コントローラーレイヤーをテストするため。モックオブジェクトを使用して必要な残りの依存関係を提供する必要があります。

参考までに、以下の注釈をいくつか追加してください。

アプリケーションのスライスのテストアプリケーション 全体を自動構成するのではなく、アプリケーションの単純な「スライス」をテストしたい場合があります。Spring Boot 1.4では、4つの新しいテストアノテーションが導入されています。

@WebMvcTest - for testing the controller layer
@JsonTest - for testing the JSON marshalling and unmarshalling
@DataJpaTest - for testing the repository layer
@RestClientTests - for testing REST clients

詳細については、https//spring.io/guides/gs/testing-web/を参照してください。


これは、Sping Boot Reference-Test Auto-configurationAnnotationsへのリンクです。ここにリストされている@ roshankumar-muthaは4つだけではありません。スタートガイドへのリンクでは、これらのスライスについて詳しく説明していません。
GeorgePantazes20年

15

MVCテストは、アプリケーションのコントローラー部分のみを対象とすることを目的としています。HTTP要求と応答はモックされるため、実際の接続は作成されません。一方、を使用@SpringBootTestすると、Webアプリケーションコンテキストのすべての構成が読み込まれ、接続は実際のWebサーバーを経由します。その場合、MockMvcBeanを使用せず、 RestTemplate代わりに標準(または新しい代替 TestRestTemplate)を使用します。

では、いつどちらを選ぶべきでしょうか?@WebMvcTestサーバー側からコントローラーを単一でテストすることを目的としています。@SpringBootTest一方、クライアント側からアプリケーションを操作する場合は、統合テストに使用する必要があります。

これは、@SpringBootTest;でモックを使用できないという意味ではありません。統合テストを作成している場合でも、それが必要になる可能性があります。いずれにせよ、単純なコントローラーの単体テストのためだけに使用しない方がよいでしょう。

ソース-SpringBootを使用したマイクロサービスの学習


4
この回答が賛成される理由がわかりません。を使用する@SpringBootTestと、webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT(またはDEFINED_PORT)があり、接続が実際のWebサーバーを経由しない限り、実際のWebサーバーは起動されません。のデフォルトは@SpringBootTestですWebEnvironment.MOCK
KorayTugay20年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.