«Это 29-й день моего участия в ноябрьском испытании обновлений. Подробную информацию об этом событии см.:Вызов последнего обновления 2021 г."
Эта статья была«Весенняя загрузка в действии»Коллекция столбцов.
Привет, я смотрю на гору.
Сегодня поговорим о том, как интегрировать Junit5, MockMvc и Mocktio в SpringBoot. Junit5 является наиболее широко используемой средой тестирования в стеке Java, и Junit4 когда-то доминировал в этом списке.
После обновления до Junit5, помимо добавления многих функций Java8, было сделано множество функциональных улучшений, оптимизирована и скорректирована структура, а также разделено множество различных модулей, которые можно вводить по мере необходимости, например:
- Платформа JUnit — запуск тестовой среды на JVM.
- JUnit Jupiter — Написание тестов и расширений в JUnit5
- JUnit Vintage — предоставляет тестовый движок для запуска тестов на основе JUnit3 и JUnit4.
Начиная с SpringBoot 2.2.0, Junit5 стала версией Junit по умолчанию. Благодаря JUnit Vintage стоимость перехода с Junit4 на Junit5 чрезвычайно низка. Итак, эта статья начинается непосредственно с Junit5.
Версия
Давайте сначала поговорим о версии, чтобы избежать всевозможных странных проблем из-за различий версий:
- JDK: jdk8 (дополнительную версию можно игнорировать)
- Спрингбут: 2.5.2
- наследовать
spring-boot-starter-parent
- полагаться
spring-boot-starter-web
- полагаться
spring-boot-starter-test
- наследовать
- Юнит: 5.7.2
- Мокито: 3.9.0
- подколенный гребень: 2,2
Преимущество SpringBoot в том, что до тех пор, пока наследованиеspring-boot-starter-parent
или представитьspring-boot-dependencies
, затем добавьтеspring-boot-starter-test
Зависеть от этого. Содержимое определенного POM выглядит следующим образом:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.2</version>
</parent>
<groupId>cn.howardliu.effective.spring</groupId>
<artifactId>springboot-junit5-mockito</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot-junit5-mockio</name>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
из-за наследстваspring-boot-starter-parent
, поэтому мы полагаемся наspring-boot-starter-test
Нет необходимости писать конкретную версию, и определение версии родителя может быть напрямую интегрировано. в,spring-boot-starter-web
представляет собой веб-контейнер для обслуживания REST API,spring-boot-starter-test
Могут быть предоставлены различные тестовые среды,spring-boot-maven-plugin
— это плагин, который упаковывает приложения SpringBoot в виде исполняемых файлов jar.
Структура проекта
Поскольку это пример DEMO, мы реализуем интерфейс Echo, который может получать параметры запроса и возвращать обработанную строку. По соглашению мы используем всемогущийHello, World!
.
Структура нашего проекта выглядит следующим образом:
├── pom.xml
└── src
├── main
│ ├── java
│ │ └── cn
│ │ └── howardliu
│ │ └── effective
│ │ └── spring
│ │ └── springbootjunit5mockio
│ │ ├── SpringbootJunit5MockioApplication.java
│ │ ├── controller
│ │ │ └── EchoController.java
│ │ └── service
│ │ ├── EchoService.java
│ │ └── impl
│ │ └── EchoServiceImpl.java
│ └── resources
│ └── application.yaml
└── test
└── java
└── cn
└── howardliu
└── effective
└── spring
└── springbootjunit5mockio
└── controller
├── EchoControllerMockTest.java
└── EchoControllerNoMockitoTest.java
- SpringbootJunit5MockioApplication: запись запуска приложения SpringBoot
- EchoController: определение интерфейса
- EchoService: реализация интерфейса бизнес-логики
- EchoServiceImpl: реализация интерфейса
- EchoControllerMockTest: реализовано с использованием фиктивного прокси-сервера EchoService.
- EchoControllerNoMockitoTest: непосредственная тестовая реализация интерфейса.
EchoServiceImpl
Давайте посмотримEchoService
, который будет основной реализацией нашего DEMO:
@Service
public class EchoServiceImpl implements EchoService {
@Override
public String echo(String foo) {
return "Hello, " + foo;
}
}
EchoControllerNoMockitoTest
Сначала мы используем Junit5+MockMvc для реализации обычного вызова интерфейса Controller, код выглядит следующим образом:
@SpringBootTest(classes = SpringbootJunit5MockioApplication.class)
@AutoConfigureMockMvc
class EchoControllerNoMockitoTest {
@Autowired
private MockMvc mockMvc;
@Test
void echo() throws Exception {
final String result = mockMvc.perform(
MockMvcRequestBuilders.get("/echo/")
.param("name", "看山")
)
.andExpect(MockMvcResultMatchers.status().isOk())
.andDo(MockMvcResultHandlers.print())
.andReturn()
.getResponse()
.getContentAsString(StandardCharsets.UTF_8);
Assertions.assertEquals("Hello, 看山", result);
}
}
мы проходимSpringBootTest
Аннотация определяет, что это тестовый пример для приложения SpringBoot, а затем передаетAutoConfigureMockMvc
Запустите тестовый контейнер. Таким образом, вы можете напрямую вводитьMockMvc
Экземпляр тестирует интерфейс контроллера.
Здесь следует отметить одну вещь: многие онлайн-учебники позволят вам написать@ExtendWith({SpringExtension.class})
Такая заметка на самом деле совершенно не нужна. Из исходного кода мы можем знать,SpringBootTest
Заметки были добавленыExtendWith
.
EchoControllerMockTest
В этом тестовом примере мы проксируем через компонент Mockito.EchoService
изecho
метод, код выглядит следующим образом:
@SpringBootTest(classes = SpringbootJunit5MockioApplication.class)
@ExtendWith(MockitoExtension.class)
@AutoConfigureMockMvc
class EchoControllerMockTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private EchoService echoService;
@BeforeEach
void setUp() {
Mockito.when(echoService.echo(Mockito.any()))
.thenReturn("看山说:" + System.currentTimeMillis());
}
@Test
void echo() throws Exception {
final String result = mockMvc.perform(
MockMvcRequestBuilders.get("/echo/")
.param("name", "看山的小屋")
)
.andExpect(MockMvcResultMatchers.status().isOk())
.andDo(MockMvcResultHandlers.print())
.andReturn()
.getResponse()
.getContentAsString(StandardCharsets.UTF_8);
Assertions.assertTrue(result.startsWith("看山"));
}
}
В этом примере нам нужно обратить внимание на@ExtendWith(MockitoExtension.class)
Аннотация, эта аннотация используется для ознакомленияMockBean
Да, мы пройдемecho
Перехват метода заставляет его возвращать результат ответа, который мы определили. Этот метод позволяет избежать необходимости фактического вызова интерфейса при тестировании нескольких систем или нескольких функций.
Например, нам нужно получить номер мобильного телефона пользователя.Обычно мы будем проверять, вошел ли пользователь в систему в интерфейсе.Мы можем использовать возможность Mockito проксировать проверку входа, чтобы результат всегда был верным.
Вывод в конце статьи
На данный момент мы завершили пример интеграции SpringBoot с Junit5, MockMvc и Mockito. Если вы хотите получить исходный код, вам просто нужно обратить внимание на публичный аккаунт «Хижина на горе» и ответить «весна».
Многие студенты считают, что нет необходимости писать модульные тесты, и они могут хорошо протестировать интерфейс, напрямую используя такие инструменты, как Swagger или Postman. Ведь для простых CRUD-интерфейсов писать юнит-тесты не очень-то и нужно. А как насчет сложных интерфейсов? Комбинаций параметров интерфейса много, и результаты ответа тоже нуждаются в различных проверках.Если использовать одноразовый инструмент, каждый раз тестировать параметры комбинации, это уже будет вызывать у людей крах, а параметры комбинации не могут быть сохранены или даже передаваться по наследству нескольким людям, что приведет к потере большого количества рабочей силы.
В этот момент проявится эффект модульного тестирования. Нам нужно только один раз написать комбинацию параметров, поместить ее в файл, такой как csv, и запустить ее несколько раз, чтобы проверить правильность интерфейса с помощью параметризованного тестового метода модульного тестирования.
Или, когда мы чувствуем, что система была заполнена запахом, его реконструкция, чтобы проверить те же функции интерфейса, можно напрямую можно проверить с помощью исходного тестового корпуса.
Подводя итог, хотя написание тестовых случаев хлопотно, это бесконечно полезно.
Рекомендуемое чтение
- SpringBoot Combat: элегантный ответ для достижения результата
- Борьба с SpringBoot: как изящно обрабатывать исключения
- Бои SpringBoot: динамическая инъекция генератора идентификаторов через BeanPostProcessor
- SpringBoot Combat: пользовательский фильтр элегантно получает параметры запроса и результаты ответа
- Бои SpringBoot: элегантное использование параметров перечисления
- Бои SpringBoot: элегантное использование параметров перечисления (принцип)
- Бой SpringBoot: элегантное использование параметров перечисления в RequestBody
- Бой SpringBoot: элегантное использование параметров перечисления в RequestBody (принцип)
- SpringBoot бой: JUnit5+MockMvc+Mockito проводят модульное тестирование
- SpringBoot Combat: загрузка и чтение содержимого файла ресурсов
Привет, я смотрю на гору. Плавайте в мире кода, играйте и наслаждайтесь жизнью. Если статья была вам полезна, ставьте лайк, добавляйте в закладки и подписывайтесь. Приглашаем обратить внимание на паблик-аккаунт «Глядя на горную хижину» и открыть для себя другой мир.