Эта статья была впервые опубликована на моем личном сайте:Использование Mockito в проектах Spring Boot
Spring Boot может работать с большинством популярных сред тестирования: создавать модульные тесты через Spring JUnit; генерировать тестовые данные для инициализации базы данных для тестирования; Spring Boot может работать с инструментами BDD (Behavier Driven Development), Cucumber и Spock для тестирования приложений.
Занимаясь разработкой программного обеспечения, мы пишем много кода, но через полгода (или даже больше года) вы знаете, как работает ваш код? Ремонтопригодность системы может быть гарантирована посредством тестирования (модульное тестирование, интеграционное тестирование, тестирование интерфейса), а когда мы модифицируем какой-либо код, регрессионное тестирование может проверить, появляются ли новые ошибки. В общем, тестирование делает систему менее «черным ящиком» и позволяет разработчикам подтвердить, что систему можно использовать.
В веб-приложении обычно существует два метода тестирования уровня контроллера: (1) отправка HTTP-запроса; (2) имитация объекта HTTP-запроса. Первый метод требует настройки среды регрессии и расчета покрытия путем изменения стратегии статистики кода; второй метод является более формальной идеей, но он мало используется в проектах, с которыми я сталкивался до сих пор.Сегодня я подведу итоги. как использовать Mock.Object тестирует код слоя контроллера.
В предыдущих статьях мы использовали приложение bookpub в качестве примера, и сегодняшний день не является исключением, готовый проверить, может ли предоставляемый им интерфейс RESTful возвращать правильные данные ответа. Этот тест отличается отмодульный тест, для которого необходимо инициализировать полный контекст приложения, вплетены все spring bean-компоненты, и в базе данных должны быть тестовые данные, обычно этот тест называетсяИнтеграционное тестированиеилитест интерфейса.
настоящий бой
Новый проект Spring Boot через spirng.io предоставляет пустой тестовый файл —BookPubApplicationTest.java, содержание такое:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = BookPubApplication.class)
public class BookPubApplicationTests {
@Test
public void contextLoads() {
}
}
- добавить в файл pomspring-boot-starter-testЗависимость, добавить зависимость jsonPath
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
</dependency>
- Добавить тестовый пример в BookPubApplicationTest
package com.test.bookpub;
import com.test.bookpub.domain.Book;
import com.test.bookpub.repository.BookRepository;
import org.junit.Before;import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.boot.test.TestRestTemplate;
import org.springframework.boot.test.WebIntegrationTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.context.WebApplicationContext;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.hamcrest.Matchers.containsString;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = BookPubApplication.class)
@WebIntegrationTest("server.port:0")
public class BookPubApplicationTests {
@Autowired
private WebApplicationContext context;
@Autowired
private BookRepository bookRepository;
@Value("${local.server.port}")
private int port;
private MockMvc mockMvc;
private RestTemplate restTemplate = new TestRestTemplate();
@Before
public void setupMockMvc() {
mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
}
@Test
public void contextLoads() {
assertEquals(1, bookRepository.count());
}
@Test
public void webappBookIsbnApi() {
Book book = restTemplate.getForObject("http://localhost:" + port +"/books/9876-5432-1111", Book.class);
assertNotNull(book);
assertEquals("中文测试", book.getPublisher().getName());
}
@Test
public void webappPublisherApi() throws Exception {
//MockHttpServletRequestBuilder.accept方法是设置客户端可识别的内容类型
//MockHttpServletRequestBuilder.contentType,设置请求头中的Content-Type字段,表示请求体的内容类型
mockMvc.perform(get("/publishers/1")
.accept(MediaType.APPLICATION_JSON_UTF8))
.andExpect(status().isOk())
.andExpect(content().string(containsString("中文测试")))
.andExpect(jsonPath("$.name").value("中文测试"));
}
}
- Покрытие кода весеннего загрузочного проекта
Используйте cobertura, обратитесь к адресу github проекта:spring boot template
# To create test coverage reports (in target/site/cobertura)
mvn clean cobertura:cobertura test
анализировать
Сначала проанализируйтеBookPubApplicationTestsАннотации, используемые в классе:
- @RunWith(SpringJUnit4ClassRunner.class), это аннотация JUnit, через эту аннотацию пустьSpringJUnit4ClassRunnerЭтот класс предоставляет тестовый контекст Spring.
- @SpringApplicationConfiguration(classes = BookPubApplication.class), который является аннотацией Spring Boot.Для интеграционного тестирования вам необходимо загрузить и настроить контекст приложения Spring с помощью этой аннотации. Это метааннотация, содержащая@ContextConfiguration( loader = SpringApplicationContextLoader.class)В этой аннотации тестовая среда использует платформу Spring Boot.SpringApplicationContextLoaderЗагрузчик создает контекст приложения.
- @WebIntegrationTest("server.port:0"), эта аннотация указывает на то, что текущий тест является интеграционным тестом (интеграционным тестом), поэтому ему необходимо инициализировать полный контекст и запустить приложение. Эта аннотация в целом и@SpringApplicationConfigurationпоявляются вместе.server.port:0Это означает, что Spring Boot запускает службу Tomcat на произвольном порту, а затем программа проходит тест.@Value("${local.server.port}")Получите этот номер порта и назначьте его переменной порта. Эта возможность произвольного получения портов может обеспечить параллелизм тестовых программ при их запуске на Jenkins или других серверах непрерывной интеграции.
Разобравшись с аннотациями тестового класса, давайте взглянем внутрь тестового класса. Поскольку это тест Spring Boot, мы можем вплести любой объект, управляемый Spring, с помощью аннотации @Autowired или установить значение указанной переменной среды с помощью @Value . Теперь в этом тестовом классе мы определяемWebApplicationContextа такжеBookRepositoryобъект.
Каждый тестовый пример украшен аннотацией @Test. В первом тестовом случае - метод contextLoads(), мне просто нужно подтвердитьBookRepositoryСоединение установлено, и соответствующие тестовые данные содержатся в базе данных.
Второй тестовый пример используется для проверки предоставленного нами URL-адреса RESTful — запрос книги по ISBN, то есть «/books/{isbn}». В этом тестовом случае мы используемTestRestTemplateОбъект инициирует запрос RESTful.
Третий тестовый пример показывает, как пройтиMockMvcОбъект реализует ту же функциональность, что и второй тест. Инфраструктура тестирования Spring предоставляет объекты MockMvc, которые могут выполнять тестирование MVC без необходимости запросов клиент-сервер.Запросы контроллера могут выполняться полностью на стороне сервера, как и при запуске тестового сервера.
Перед началом теста необходимо установить тестовую среду, а метод установки изменить с помощью @Before. пройти черезMockMvcBuildersИнструмент, используя объект WebApplicationContext в качестве параметра, создает объект MockMvc.
Объект MockMvc предоставляет набор функций инструмента для выполнения оценок утверждений, все из которых являются оценками для веб-запросов. Этот набор инструментов используется функциями объединения в цепочку, что позволяет программистам связывать вместе несколько тестовых случаев и делать несколько суждений. В этом примере мы используем некоторые из следующих вспомогательных функций:
- perform(get(...))Сделать веб-запрос. В нашем третьем варианте использованияMockMvcRequestBuilderВыполнить GET-запрос.
- andExpect(...)Ее можно вызывать несколько раз после вызова функции execute(...), что указывает на оценку нескольких условий.Тип параметра этой функции:ResultMatcherинтерфейс, вMockMvcResultMatchersЭтот класс обеспечивает много возвратовResultMatcherПолезная функция интерфейса. Эта функция позволяет обнаруживать несколько аспектов одного и того же веб-запроса, включая код состояния ответа HTTP (статус ответа), тип содержимого ответа (тип содержимого), значение, хранящееся в сеансе, проверку содержимого перенаправлений, модели или заголовки и т.д. Тут нужно передать стороннюю библиотекуjson-pathОбнаружение данных ответа в формате JSON: убедитесь, что данные json содержат правильный тип элемента и соответствующее значение, напримерjsonPath("$.name").value("Китайский тест")Он используется для проверки того, что в корневом каталоге есть узел с именем name, и соответствующее значение этого узла — «китайский тест».
Проблема искажения персонажа
- Описание проблемы: пройтиspring-boot-starter-data-restУстановленный репозиторий, вынутые китайские иероглифы искажаются.
- Анализ: нет проблем с использованием проверки postman и httpie, что указывает на то, что тестовый пример Mockmvc написан неправильно.Вы должны активно установить, как клиент анализирует ответ HTTP, и использовать метод get.accept для установки типа контента, который клиент можно распознать.Измененный тестовый пример выглядит следующим образом:
@Test
public void webappPublisherApi() throws Exception {
//MockHttpServletRequestBuilder.accept方法是设置客户端可识别的内容类型
//MockHttpServletRequestBuilder.contentType,设置请求头中的Content-Type字段,表示请求体的内容类型
mockMvc.perform(get("/publishers/1")
.accept(MediaType.APPLICATION_JSON_UTF8))
.andExpect(status().isOk())
.andExpect(content().string(containsString("中文测试")))
.andExpect(jsonPath("$.name").value("中文测试"));
}
использованная литература
- Интеграционное тестирование Restful API на базе Spring-WS
- Маленькие вещи, которые нужно знать о J2EE - Иллюстрация протокола HTTP
- Integration Testing a Spring Boot Application
- spring boot project template
Весенняя загрузка серии 1.x
- Автоматическая настройка Spring Boot, Command-line-Runner
- Понимание автоматической настройки Spring Boot
- Использование аннотации Spring Boot @PropertySource при интеграции Redis
- Как настроить преобразователи HTTP-сообщений в проектах Spring Boot
- Spring Boot интегрирует Mongodb для обеспечения интерфейса Restful.
- Сфера фасоли весной
- Использование шаблона диспетчера событий в проекте Spring Boot
- Методы обработки ошибок, когда Spring Boot предоставляет интерфейсы RESTful
- Настройка собственного стартера в Spring Boot
- Как проекты Spring Boot поддерживают протоколы HTTP и HTTPS
- Как пользовательский стартер Spring Boot настраивает аннотации автоконфигурации
*** В этом выпуске основное внимание уделяется таким темам, как серверные технологии, устранение неполадок и оптимизация JVM, вопросы на собеседованиях по Java, личностный рост и самоуправление, а читателям предлагается опыт работы и роста передовых разработчиков. получить что-то здесь.