SpringCloud單元測試【六】


SpringCloud的單元測試主要是依靠 Mock以及Mockito, 所以我們需要對Mock以及Mockito有一定的認識。

一、為什么要用MockMvc

  可能我們在測試控制層的代碼都是啟動服務器,在瀏覽器中輸入URL,然后開始測試是否達到預期效果,發生錯誤的話,修改相關代碼並重啟服務器再次進行測試。分析一下這個過程,啟動服務器-->打開瀏覽器-->輸入URL-->等待返回結果-->修復bug-->重啟服務器.....循環。
  其中的缺點也挺明顯的,在瀏覽器輸入URL的地址,如果是GET請求還好,POST請求或者DELETE請求怎么辦?只能借助其他工具,通過命令行編寫curl語句,或者借助谷歌瀏覽器的postman插件,亦或者自己在代碼中通過編寫相應httpClient方法來實現測試,但是這幾種方法都較為麻煩,而且測試用例並不能較好的保存。再說一個缺點,代碼修改后,往往需要再次重啟服務器,等待啟動完畢才能接下來的測試過程。
  如果tomcat服務器啟動速度較慢,這將是一件非常痛苦的事情,測試驗證也不方便,且依賴網絡環境,這些原因導致測試起來很麻煩,而為了可以方便對Controller進行測試,且很好的保存和循環使用測試用例,則可以通過單元測試來解決,通過前面一篇文章,大家對於單元測試的便利性有了認識和體會,接下來通過引入MockMVC進行控制層的單元測試。

  MockMvc實現了對Http請求的模擬,能夠直接使用網絡的形式,轉換到Controller的調用,這樣可以使得測試速度快、不依賴網絡環境,而且提供了一套驗證的工具,這樣可以使得請求的驗證統一而且很方便。

二、示例演示

1. pom.xml中引入依賴

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

2. 編寫測試類

在測試類前加上注解

@RunWith(SpringRunner.class)
@SpringBootTest(classes = EurekaClientApplication.class) //EurekaClientApplication是模塊的啟動類名
@WebAppConfiguration
@ContextConfiguration

再加上

@Autowired
private WebApplicationContext context;

private MockMvc mvc;

再加上一個before

@Before
public void setUp() throws Exception {
        mvc = MockMvcBuilders
                .webAppContextSetup(context)
                .build();
}

在真實需要測試的代碼中加入

@Test
public void contextLoads() throws Exception {
    MvcResult 
//groupManager訪問路徑
//param傳入參數
result=mvc.perform(MockMvcRequestBuilders.post("/groupManager").param("pageNum","1").param("pageSize","10")).andReturn();
    MockHttpServletResponse response = result.getResponse();
    String content = response.getContentAsString();
    List<JtInfoDto> jtInfoDtoList = GsonUtils.toObjects(content, new TypeToken<List<JtInfoDto>>() {}.getType());
    for(JtInfoDto infoDto : jtInfoDtoList){
        System.out.println(infoDto.getJtCode());
    }
}

3. 數據庫回滾

在測試類上添加注解@Rollback,同時測試方法加上注解@Transactional。

如果不希望回滾 將rollback改為false即可

4. 完整的測試代碼

@RunWith(SpringRunner.class)
@SpringBootTest(classes = EurekaClientApplication.class)
@WebAppConfiguration
@ContextConfiguration
public class EurekaClientApplicationTests {

    @Autowired
    private WebApplicationContext context;

    private MockMvc mvc;

    @Before
    public void setUp() throws Exception {
        mvc = MockMvcBuilders
                .webAppContextSetup(context)
                .build();
    }

    @Test
    public void contextLoads() throws Exception {
        MvcResult result=mvc.perform(MockMvcRequestBuilders.post("/groupManager").param("pageNum","1").param("pageSize","10")).andReturn();
        MockHttpServletResponse response = result.getResponse();
        String content = response.getContentAsString();
        List<JtInfoDto> jtInfoDtoList = GsonUtils.toObjects(content, new TypeToken<List<JtInfoDto>>() {}.getType());
        for(JtInfoDto infoDto : jtInfoDtoList){
            System.out.println(infoDto.getJtCode());
        }
    }

}

注意:我們大多數的時候是往控制層controller傳遞的不是一個簡單的參數,可能是一個Map或一個實體類,發現怎么都傳不過去,解決方法如下:

在發送請求的時候,我們使用json的參數格式 

     Map params = new HashMap();
        params.put("name", "西瓜");
        params.put("unit","斤");
        params.put("price", "12.88");
        String requestJson = JSONObject.toJSONString(params);
        MvcResult result = mockMvc.perform(MockMvcRequestBuilders.post("/good/save")
                .contentType(MediaType.APPLICATION_JSON).content(requestJson))
                .andDo(MockMvcResultHandlers.print())
                .andExpect(MockMvcResultMatchers.status().is(200))
                .andReturn();
        result.getResponse().setCharacterEncoding("UTF-8");
        System.out.println(result.getResponse().getContentAsString());

然后controller的參數添加@RequestBody注解。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM