Zombando de um RestTemplate na primavera
1. Introdução
Freqüentemente, nos deparamos com aplicativos que realizam algum tipo de solicitação da web. Quando se trata de testar esse comportamento, temos algunsoptions com aplicativos Spring.
In this quick tutorial, we’ll look at just a couple of ways of mocking such calls performed only through a RestTemplate.
Vamos começar a testar com Mockito, uma biblioteca popular de mocking. Em seguida, usaremos o Spring Test, que nos fornece um mecanismo para criar um servidor simulado para definir as interações do servidor.
2. UsandoMockito
Poderíamos usar o Mockito para zombar do saltoRestTemplate juntos. Com essa abordagem, testar nosso serviço seria tão simples quanto qualquer outrotest involving mocking.
Vamos supor que temos uma classeEmployeeService simples, que busca detalhes do funcionário por meio de HTTP:
@Service
public class EmployeeService {
@Autowired
private RestTemplate restTemplate;
public Employee getEmployee(String id) {
ResponseEntity resp =
restTemplate.getForEntity("http://localhost:8080/employee/" + id, Employee.class);
return resp.getStatusCode() == HttpStatus.OK ? resp.getBody() : null;
}
}
Vamos implementar nosso teste para o código anterior: __
@RunWith(MockitoJUnitRunner.class)
public class EmployeeServiceTest {
@Mock
private RestTemplate restTemplate;
@InjectMocks
private EmployeeService empService = new EmployeeService();
@Test
public void givenMockingIsDoneByMockito_whenGetIsCalled_shouldReturnMockedObject() {
Employee emp = new Employee(“E001”, "Eric Simmons");
Mockito
.when(restTemplate.getForEntity(
“http://localhost:8080/employee/E001”, Employee.class))
.thenReturn(new ResponseEntity(emp, HttpStatus.OK));
Employee employee = empService.getEmployee(id);
Assert.assertEquals(emp, employee);
}
}
Na classe de teste JUnit acima, pedimos primeiro ao Mockito para criar uma instância fictíciaRestTemplate usando a anotação@Mock.
Em seguida, anotamos a instânciaEmployeeService com@InjectMocks para injetar a instância fictícia nela.
Finalmente, no método de teste, definimos o comportamento do nosso mock usandoMockito’s when/then support.
3. Usando o Spring Test
O módulo de teste Spring inclui um servidor simulado chamadoMockRestServiceServer.With this approach, we configure the server to return a particular object when a specific request is dispatched through our RestTemplate instance. Finalmente, podemosverify() nessa instância do servidor, quer todas as expectativas tenham sido atendidas ou não.
MockRestServiceServer realmente funciona interceptando as chamadas de API HTTP usando umMockClientHttpRequestFactory. Com base em nossa configuração, ele cria uma lista de solicitações esperadas e respostas correspondentes. Quando a instânciaRestTemplate chama a API, ela pesquisa a solicitação em sua lista de expectativas e retorna a resposta correspondente.
Assim, elimina a necessidade de executar um servidor HTTP em qualquer outra porta para o envio de respostas simuladas.
Vamos criar um teste simples para o mesmo exemplogetEmployee() usandoMockRestServiceServer:
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = SpringTestConfig.class)
public class EmployeeServiceMockRestServiceServerUnitTest {
@Autowired
private EmployeeService empService;
@Autowired
private RestTemplate restTemplate;
private MockRestServiceServer mockServer;
private ObjectMapper mapper = new ObjectMapper();
@Before
public void init() {
mockServer = MockRestServiceServer.createServer(restTemplate);
}
@Test
public void givenMockingIsDoneByMockRestServiceServer_whenGetIsCalled_thenReturnsMockedObject()() {
Employee emp = new Employee("E001", "Eric Simmons");
mockServer.expect(ExpectedCount.once(),
requestTo(new URI("http://localhost:8080/employee/E001")))
.andExpect(method(HttpMethod.GET))
.andRespond(withStatus(HttpStatus.OK)
.contentType(MediaType.APPLICATION_JSON)
.body(mapper.writeValueAsString(emp))
);
Employee employee = empService.getEmployee(id);
mockServer.verify();
Assert.assertEquals(emp, employee);
}
}
No snippet anterior, usamos métodos estáticos deMockRestRequestMatcherseMockRestResponseCreators para definir a expectativa e a resposta para a chamada REST de uma maneira clara e legível:
import static org.springframework.test.web.client.match.MockRestRequestMatchers.*;
import static org.springframework.test.web.client.response.MockRestResponseCreators.*;
Devemos ter em mente queRestTemplate na classe de teste deve ser a mesma instância usada na classeEmployeeService. Para garantir isso, definimos um bean RestTemplate na configuração da primavera e conectamos automaticamente a instância no teste e na implementação:
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
Usar umMockRestServiceServer é muito útil quando escrevemos nossos testes de integração e só precisamos simular chamadas HTTP externas.
4. Conclusão
Neste breve artigo, discutimos algumas opções eficazes para zombar das chamadas externas da API REST por HTTP ao escrever testes de unidade.
O código-fonte do artigo acima está disponívelover on GitHub.