Eu sou novo no Spring Boot e estou tentando entender como funcionam os testes no SpringBoot. Estou um pouco confuso sobre qual é a diferença entre os dois seguintes snippets de código:
Snippet de código 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!")));
}
}
Este teste usa a @WebMvcTest
anotação que acredito ser para teste de fatia de recurso e testa apenas a camada MVC de um aplicativo da web.
Snippet de código 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!")));
}
}
Este teste usa a @SpringBootTest
anotação e a MockMvc
. Então, como isso é diferente do trecho de código 1? O que isso faz de diferente?
Edit: Adicionando trecho de código 3 (encontrado como um exemplo de teste de integração na documentação do 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!"));
}
}
fonte
SpringBootTest
está carregando seu aplicativo completo (até certo ponto, por padrão, ele não iniciará o contêiner incorporado se houver um disponível, é para isso quewebEnvironment
existe). Eu não diria que@SpringBootTest
é um teste de unidade do controlador, mas mais um teste de integração, na verdade.WebMvcTest
é realmente um teste de unidade do seu controlador no sentido de que, se ele tiver dependência, você terá que fornecê-los você mesmo (uma configuração ou algum tipo de simulação).SpringBootTest
eWebMvcTest
criado são muito diferentes. O primeiro carrega TODO o seu aplicativo e ativa TODAS as configurações automáticas, enquanto o último só ativa o Spring Mvc e não verifica nada além deHelloController
. Afinal, tudo depende do que você entende por teste de unidade. Mas essa é a diferença.A anotação @SpringBootTest diz ao Spring Boot para ir e procurar por uma classe de configuração principal (uma com @SpringBootApplication por exemplo) e usá-la para iniciar um contexto de aplicativo Spring. SpringBootTest carrega o aplicativo completo e injeta todos os beans que podem ser lentos.
@WebMvcTest - para testar a camada do controlador e você precisa fornecer as dependências restantes necessárias usando objetos Mock.
Mais algumas anotações abaixo para sua referência.
Testando fatias do aplicativo Às vezes, você gostaria de testar uma simples “fatia” do aplicativo em vez de configurar automaticamente todo o aplicativo. Spring Boot 1.4 apresenta 4 novas anotações de teste:
Consulte para mais informações: https://spring.io/guides/gs/testing-web/
fonte
Os testes MVC têm como objetivo cobrir apenas a parte do controlador de sua aplicação. Solicitações e respostas HTTP são simuladas para que as conexões reais não sejam criadas. Por outro lado, ao usar
@SpringBootTest
, toda a configuração do contexto da aplicação web é carregada e as conexões estão passando pelo servidor web real. Nesse caso, você não usa oMockMvc
bean, mas um padrãoRestTemplate
(ou a nova alternativaTestRestTemplate
).Então, quando devemos escolher um ou outro?
@WebMvcTest
destina-se a testar unitariamente o controlador do lado do servidor.@SpringBootTest
, por outro lado, deve ser usado para testes de integração, quando se deseja interagir com a aplicação do lado do cliente.Isso não significa que você não pode usar mocks com
@SpringBootTest
; se você estiver escrevendo um teste de integração, isso ainda pode ser necessário. Em qualquer caso, é melhor não usá-lo apenas para um simples teste de unidade do controlador.fonte - Aprendendo microsserviços com Spring Boot
fonte
@SpringBootTest
, um servidor web real não é iniciado a menos que você também tenhawebEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT
(ou aDEFINED_PORT
) e as conexões não passem pelo servidor web real. O padrão para@SpringBootTest
éWebEnvironment.MOCK
.