Я новичок в Spring Boot и пытаюсь понять, как работает тестирование в SpringBoot. Я немного смущен тем, в чем разница между следующими двумя фрагментами кода:
Фрагмент кода 1:
@RunWith(SpringRunner.class)
@WebMvcTest(HelloController.class)
public class HelloControllerApplicationTest {
@Autowired
private MockMvc mvc;
@Test
public void getHello() throws Exception {
mvc.perform(MockMvcRequestBuilders.get("/").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(content().string(equalTo("Greetings from Spring Boot!")));
}
}
В этом тесте используется @WebMvcTest
аннотация, которая, как я полагаю, предназначена для тестирования фрагментов функций, и проверяется только уровень MVC веб-приложения.
Фрагмент кода 2:
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class HelloControllerTest {
@Autowired
private MockMvc mvc;
@Test
public void getHello() throws Exception {
mvc.perform(MockMvcRequestBuilders.get("/").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(content().string(equalTo("Greetings from Spring Boot!")));
}
}
Этот тест использует @SpringBootTest
аннотацию и файл MockMvc
. Так чем же он отличается от фрагмента кода 1? Что это делает по-другому?
Изменить: добавление фрагмента кода 3 (нашел это как пример интеграционного тестирования в документации Spring)
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class HelloControllerIT {
@LocalServerPort private int port;
private URL base;
@Autowired private TestRestTemplate template;
@Before public void setUp() throws Exception {
this.base = new URL("http://localhost:" + port + "/");
}
@Test public void getHello() throws Exception {
ResponseEntity < String > response = template.getForEntity(base.toString(), String.class);
assertThat(response.getBody(), equalTo("Greetings from Spring Boot!"));
}
}
источник
SpringBootTest
загружает ваше полное приложение (в некоторой степени, по умолчанию он не запускает встроенный контейнер, если он доступен, для чегоwebEnvironment
он нужен). Я бы не сказал, что@SpringBootTest
это юнит-тест контроллера, это скорее интеграционный тест.WebMvcTest
на самом деле является модульным тестом вашего контроллера в том смысле, что если у него есть зависимость, вам придется предоставить их самостоятельно (либо конфигурацию, либо какой-то макет).SpringBootTest
иWebMvcTest
создается, сильно различается. Первый загружает ваше ВСЕ приложение и включает ВСЕ автоконфигурации, а второй включает только Spring Mvc и не сканирует ничего, кромеHelloController
. В конце концов, все зависит от того, что вы подразумеваете под модульным тестом. Но вот в чем разница.Аннотация @SpringBootTest сообщает Spring Boot, что нужно искать основной класс конфигурации (например, с @SpringBootApplication) и использовать его для запуска контекста приложения Spring. SpringBootTest загружает полное приложение и внедряет все bean-компоненты, которые могут быть медленными.
@WebMvcTest - для тестирования уровня контроллера, и вам необходимо предоставить оставшиеся зависимости, необходимые для использования Mock Objects.
Еще несколько аннотаций ниже для справки.
Тестирование фрагментов приложения Иногда вы хотите протестировать простой «фрагмент» приложения вместо автоматической настройки всего приложения. Spring Boot 1.4 представляет 4 новых тестовых аннотации:
См. Дополнительную информацию: https://spring.io/guides/gs/testing-web/
источник
Тесты MVC предназначены для охвата только части контроллера вашего приложения. HTTP-запросы и ответы имитируются, поэтому реальные соединения не создаются. С другой стороны, при использовании
@SpringBootTest
загружается вся конфигурация контекста веб-приложения, и соединения проходят через реальный веб-сервер. В этом случае вы используете неMockMvc
bean-компонент, а его стандартRestTemplate
(или новую альтернативуTestRestTemplate
).Итак, когда мы должны выбрать одно или другое?
@WebMvcTest
предназначен для однократного тестирования контроллера со стороны сервера.@SpringBootTest
, с другой стороны, следует использовать для интеграционных тестов, когда вы хотите взаимодействовать с приложением со стороны клиента.Это не значит, что вы не можете использовать mocks
@SpringBootTest
; если вы пишете интеграционный тест, это может быть необходимо. В любом случае лучше не использовать его только для простого юнит-теста контроллера.источник - Изучение микросервисов с помощью Spring Boot
источник
@SpringBootTest
, настоящий веб-сервер не запускается, если у вас также нетwebEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT
(илиDEFINED_PORT
) и соединения не проходят через настоящий веб-сервер. По умолчанию@SpringBootTest
этоWebEnvironment.MOCK
.