2016-10-05 71 views
18

我是Spring Boot的新手,並試圖瞭解如何在SpringBoot中測試。我有點困惑的是以下兩個代碼段之間的區別:使用MockMvc與SpringBootTest和使用WebMvcTest之間的區別

代碼片段:

@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!")); 
} 
} 

回答

16

非常好的問題。

@SpringBootTest是一般測試註釋。如果你正在尋找在1.4之前做同樣事情的東西,那就是你應該使用的東西。它不會使用切片,這意味着它將啓動完整的應用程序上下文,並且根本不會自定義組件掃描。

@WebMvcTest只會掃描您定義的控制器和MVC基礎結構。而已。因此,如果您的控制器對服務層中的其他bean具有一些依賴性,那麼只有在您自己加載配置或爲其提供模擬之前,測試纔會啓動。由於我們只加載應用程序的一小部分,因此速度更快。此註釋使用切片。

Reading the doc應該也可以幫助你。

+0

非常感謝響應!。因此,如果我理解正確,那麼這意味着這兩個代碼片段僅測試應用程序的MVC部分。但是tcode代碼片段1會加載完整的應用程序上下文,而代碼片段2僅會掃描控制器。它是否正確?代碼段1是否可以被視爲測試控制器的單元測試? – Reshma

+0

不,這是不正確的。 'SpringBootTest'正在加載您的完整應用程序(在某種程度上,默認情況下,如果有可用的,它將不會啓動嵌入式容器,這就是'webEnvironment'的用途)。我不會說'@ SpringBootTest'是控制器的單元測試,但更多的是集成測試。 'WebMvcTest'實際上是對你的控制器的單元測試,因爲如果它有依賴性,你必須自己提供它們(配置或某種模擬)。 –

+0

再次感謝您的回覆。我編輯了這個問題並添加了代碼片段3.您提到@SpringBootTest註釋更多地用於集成測試。我相信Snippet 3展示了這一點。因此,如果像Snippet 3那樣完成集成測試,那麼Snippet 2會做什麼? Snippet 2使用SpringBootTest註釋和一個模擬環境(wenEnvironment屬性的默認值)。此外,代碼片段3啓動嵌入式服務器並進行真正的HTTP調用,而代碼段2不執行此操作。所以考慮到這一點,不能將snippet 2視爲單元測試? – Reshma

12

@SpringBootTest註釋告訴Spring Boot去找一個主要的配置類(例如一個帶有@SpringBootApplication的實例),並用它來啓動一個Spring應用程序上下文。 SpringBootTest加載完整的應用程序並注入可能很慢的所有bean。

@WebMvcTest - 用於測試控制器層,您需要提供使用模擬對象所需的其餘依賴關係。

以下幾個註釋供您參考。

測試應用程序 切片有時你想測試應用程序的一個簡單的「切片」,而不是自動配置整個應用程序的。春季啓動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/

相關問題