Недавно участвуя в проекте микросервисов, мы обнаружили, что после внутренних интерфейсов необходимо вызывать другие сервисы, но другие сервисы также не закончили мой барьер настройки, что очень смущает. Как в этом случае проверить? Затем нам нужно ввести понятие Mock.
1 Что такое мокап
Мок заключается в создании фиктивного объекта для имитации поведения объекта для некоторых объектов, которые нелегко построить/получить в процессе тестирования. Например, если вам нужно вызвать службу B, но служба B еще не разработана, вы можете смоделировать часть, которая вызывает службу B, и записать желаемый возвращаемый результат.
2 Библиотека тестовых классов Spring Boot
В настоящее время большинство java-сервисов построены с помощью фреймворка Spring, а Spring Boot также используется для быстрой разработки и разработки. Spring Boot предоставляет множество утилит и аннотаций, помогающих тестировать приложения, в основном включая следующие два модуля:
- spring-boot-test: поддерживает основное содержание тестирования.
- spring-boot-test-autoconfigure: поддерживает автоматическую настройку тестов.
Для разработки вы можете импортировать эти тестовые модули Spring Boot, если вы используете стартер spring-boot-starter-test, а также некоторые полезные библиотеки, такие как JUnit, AssertJ, Hamcrest и другие, следующим образом:
- JUnit: стандартная библиотека классов для модульного тестирования Java-приложений.
- Spring Test и Spring Boot Test: поддержка тестирования функциональной интеграции приложений Spring Boot.
- AssertJ: легкая библиотека утверждений.
- Mockito: среда тестирования Java Mock, которая по умолчанию платит 1.x и может быть изменена до 2.x.
- JsonPath: библиотека манипулирования JSON.
3 Напишите тестовые случаи
Представляем зависимость pom
Создайте обычный проект maven в IDEA, а затем импортируйте зависимости pom:
<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>
3.2 MockMVC на основе тестирования в стиле RESTful
Для проектов с разделенными фронтендом и бэкендом невозможно протестировать корректность интерфейса напрямую из статического кода фронтенда, поэтому для имитации HTTP-запросов можно использовать MockMVC. На основе теста RESTful SpringMVC мы можем протестировать весь процесс Spring MVC, от запроса URL-адреса до обработки контроллера для просмотра рендеринга.
Сначала создайте супер простой контроллер
@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;
}
}
запрос и ответ
@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
После написания вы можете запустить его напрямую, и вы можете увидеть подробную информацию из консоли.
4 Mockito
4.1 Что такое Мокито
Mockito — это фиктивный фреймворк, который позволяет вам тестировать чистые API. И Mockito прост в освоении, он удобочитаем, а синтаксис проверки лаконичен. Mockito — это наиболее широко используемая платформа для создания макетов на GitHub, которая используется в сочетании с JUnit. Платформа Mockito может создавать и настраивать макеты объектов. Использование Mockito упрощает разработку тестов для классов с внешними зависимостями!
4.2 Использование Мокито
присоединиться к службе
public interface WebService {
String web(String string);
}
@Service
public class WebServiceImpl implements WebService {
@Override
public String web(String string) {
return "WebServiceImpl 运行成功";
}
}
изменить контроллер
@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
Дайте макету мелодию, чтобы мы могли добавить то, что хотимwebService
Вернуть результат.
В тестовом примере мы добавилиdoReturn()
метод, значение этого кода заключается в вызовеWebService
серединаweb()
Когда методanyString()
Указывает входящийweb()
Параметры в методе могут быть любого типа String, и, конечно же, естьanyInt()
и т. д. метод), возвратMockito WebServiceImpl 运行完成
. конечно тоже нельзяWebService
Откажитесь от макета, так что вы получите нормальное возвращаемое значение.