最近在搞微服務的項目,搞完後發現內部須要調用別的服務的接口,但是另外一個服務尚未寫完我還調不通,哪這就很是尷尬了。這種狀況下要怎麼測試呢?這時就須要引入Mock的概念。前端
mock是在測試過程當中,對於一些不容易構造/獲取的對象,建立一個mock對象來模擬對象的行爲。好比說你須要調用B服務,但是B服務尚未開發完成,那麼你就能夠將調用B服務的那部分給Mock掉,並編寫你想要的返回結果。java
如今絕大多數的java服務都是Spring框架搭建的,而且也會使用到Spring boot來進行快速搭建開發,在Spring Boot提供了許多實用工具和註解來幫助測試應用程序,主要包括如下兩個模塊:web
開發進行只要使用 spring-boot-starter-test 啓動器就能引入這些 Spring Boot 測試模塊,還能引入一些像 JUnit, AssertJ, Hamcrest 及其餘一些有用的類庫,具體以下所示:spring
再IDEA中建立一個普通的maven項目便可,而後導入pom依賴:json
<parent>
<groupId> org.springframework.boot </groupId>
<artifactId> spring-boot-starter-parent </artifactId>
<version>2.1.7.RELEASE </version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.20</version>
</dependency>
</dependencies>
複製代碼
對於先後端分離的項目而言,沒法直接從前端靜態代碼中測試接口的正確性,所以能夠經過MockMVC來模擬HTTP請求。基於RESTful風格的SpringMVC的測試,咱們能夠測試完整的Spring MVC流程,即從URL請求到控制器處理,再到視圖渲染均可以測試。後端
首先建立一個超簡單的controllerbash
@RestController
@RequestMapping(value = "/web")
public class WebController {
@PostMapping(value = "/create")
public WebResponse<String> ping(@RequestBody WebRequest webRequest){
System.out.println(webRequest);
WebResponse<String> response = new WebResponse<>();
response.setBody("create 完成---");
response.setCode("00000");
response.setMessage("成功");
return response;
}
}
複製代碼
request和responseapp
@Data
@ToString
@EqualsAndHashCode
public class WebRequest {
private String name;
private String mobile;
}
複製代碼
@Data
@ToString
@EqualsAndHashCode
public class WebResponse<T> {
private String code;
private String message;
private T body;
}
複製代碼
而後建立一個測試用例類框架
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class WebControllerIT {
@Autowired
private WebApplicationContext mac;
@Autowired
private MockMvc mockMvc;
@Test
public void ping() throws Exception {
//請求的json
String json = "{\"name\":\"王五\",\"mobile\":\"12345678901\"}";
//perform,執行一個RequestBuilders請求,會自動執行SpringMVC的流程並映射到相應的控制器執行處理
mockMvc.perform(MockMvcRequestBuilders
//構造一個post請求
.post("/web/create")
//json類型
.contentType(MediaType.APPLICATION_JSON_UTF8)
//使用writeValueAsString()方法來獲取對象的JSON字符串表示
.content(json))
//andExpect,添加ResultMathcers驗證規則,驗證控制器執行完成後結果是否正確,【這是一個斷言】
.andExpect(MockMvcResultMatchers.status().is(200))
.andExpect(MockMvcResultMatchers.status().isOk())
//使用jsonPaht驗證返回的json中code字段的返回值
.andExpect(MockMvcResultMatchers.jsonPath("$.code").value("00000"))
.andExpect(MockMvcResultMatchers.jsonPath("$.message").value("成功"))
//body屬性不爲空
.andExpect(MockMvcResultMatchers.jsonPath("$.body").isNotEmpty())
//添加ResultHandler結果處理器,好比調試時 打印結果(print方法)到控制檯
.andDo(MockMvcResultHandlers.print())
//返回相應的MvcResult
.andReturn();
}
}
複製代碼
其中MockMvcRequestBuilders
寫好後直接運行就能夠了,從控制檯就能夠看到詳細信息。前後端分離
Mockito是mocking框架,它讓你用簡潔的API作測試。並且Mockito簡單易學,它可讀性強和驗證語法簡潔。 Mockito是GitHub上使用最普遍的Mock框架,並與JUnit結合使用.Mockito框架能夠建立和配置mock對象.使用Mockito簡化了具備外部依賴的類的測試開發!
加入一個service
public interface WebService {
String web(String string);
}
複製代碼
@Service
public class WebServiceImpl implements WebService {
@Override
public String web(String string) {
return "WebServiceImpl 運行成功";
}
}
複製代碼
修改controller
@RestController
@RequestMapping(value = "/web")
public class WebController {
@Autowired
private WebService webService;
@PostMapping(value = "/create")
public WebResponse<String> ping(@RequestBody WebRequest webRequest){
//調用service
String str = webService.web(webRequest.getMobile());
WebResponse<String> response = new WebResponse<>();
response.setBody(str);
response.setCode("00000");
response.setMessage("成功");
return response;
}
}
複製代碼
修改測試用例
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class WebControllerIT {
@Autowired
private WebApplicationContext mac;
@Autowired
private MockMvc mockMvc;
@MockBean
private WebService webService;
@Test
public void ping() throws Exception {
doReturn("Mockito WebServiceImpl 運行完成").when(webService).web(anyString());
//請求的json
String json = "{\"name\":\"王五\",\"mobile\":\"12345678901\"}";
//perform,執行一個RequestBuilders請求,會自動執行SpringMVC的流程並映射到相應的控制器執行處理
mockMvc.perform(MockMvcRequestBuilders
//構造一個post請求
.post("/web/create")
//json類型
.contentType(MediaType.APPLICATION_JSON_UTF8)
//使用writeValueAsString()方法來獲取對象的JSON字符串表示
.content(json))
//andExpect,添加ResultMathcers驗證規則,驗證控制器執行完成後結果是否正確,【這是一個斷言】
.andExpect(MockMvcResultMatchers.status().is(200))
.andExpect(MockMvcResultMatchers.status().isOk())
//使用jsonPaht驗證返回的json中code字段的返回值
.andExpect(MockMvcResultMatchers.jsonPath("$.code").value("00000"))
.andExpect(MockMvcResultMatchers.jsonPath("$.message").value("成功"))
//body屬性不爲空
.andExpect(MockMvcResultMatchers.jsonPath("$.body").isNotEmpty())
//添加ResultHandler結果處理器,好比調試時 打印結果(print方法)到控制檯
.andDo(MockMvcResultHandlers.print())
//返回相應的MvcResult
.andReturn();
}
}
複製代碼
輸出結果:
從上面的代碼能夠看到,咱們新增了一個webService
,並增長了
@MockBean
註解,表示將
webService
給mock調,這樣咱們就能夠增長本身想要得
webService
返回結果。 在測試用例中咱們增長了
doReturn()
方法,這段代碼的含義是當調用
WebService
中的
web()
方法時(
anyString()
表示傳入
web()
方法中的參數是任意的String類型,固然還有個
anyInt()
等方法),返回
Mockito WebServiceImpl 運行完成
。固然你也能夠不將
WebService
給mock掉,這樣拿到的就是正常的返回值。