Se moquer d'un RestTemplate au printemps

1. Introduction

Souvent, nous nous trouvons avec des applications qui effectuent une sorte de requête Web. Quand il s'agit de tester ce comportement, nous avons quelques options avec les applications Spring.

Dans ce tutoriel rapide, nous allons examiner quelques moyens de se moquer de ces appels effectués uniquement via un RestTemplate .

Nous allons commencer à tester avec Mockito, une bibliothèque moqueuse populaire. Ensuite, nous utiliserons Spring Test qui nous fournit un mécanisme pour créer un serveur fictif pour définir les interactions du serveur.

2. Utilisation de Mockito

Nous pourrions utiliser Mockito pour nous moquer complètement du RestTemplate . Avec cette approche, tester notre service serait aussi simple que tout autre test impliquant des moqueries.

Supposons que nous ayons une classe EmployeeService simple , qui récupère les détails des employés via HTTP:

@Service public class EmployeeService { @Autowired private RestTemplate restTemplate; public Employee getEmployee(String id) { ResponseEntity resp = restTemplate.getForEntity("//localhost:8080/employee/" + id, Employee.class); return resp.getStatusCode() == HttpStatus.OK ? resp.getBody() : null; } } 

Implémentons notre test pour le code précédent:

@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( “//localhost:8080/employee/E001”, Employee.class)) .thenReturn(new ResponseEntity(emp, HttpStatus.OK)); Employee employee = empService.getEmployee(id); Assert.assertEquals(emp, employee); } }

Dans la classe de test JUnit ci-dessus, nous avons d'abord demandé à Mockito de créer une instance factice de RestTemplate à l' aide de l' annotation @Mock .

Ensuite, nous avons annoté l' instance EmployeeService avec @InjectMocks pour y injecter l'instance factice.

Enfin, dans la méthode de test, nous avons défini le comportement de notre maquette en utilisant le support when / then de Mockito.

3. Utilisation de Spring Test

leLe module Spring Test comprend un serveur fictif nommé MockRestServiceServer. Avec cette approche, nous configurons le serveur pour renvoyer un objet particulier lorsqu'une demande spécifique est distribuée via notre instance RestTemplate . Enfin, nous pouvons vérifier () sur cette instance de serveur si toutes les attentes ont été satisfaites ou non.

MockRestServiceServer fonctionne en fait en interceptant les appels d'API HTTP à l'aide d'un MockClientHttpRequestFactory . Sur la base de notre configuration, il crée une liste des demandes attendues et des réponses correspondantes. Lorsque l' instance RestTemplate appelle l'API, elle recherche la requête dans sa liste d'attentes et renvoie la réponse correspondante.

Ainsi, il élimine le besoin d'exécuter un serveur HTTP sur tout autre port pour envoyer des réponses simulées.

Créons un test simple pour le même exemple getEmployee () en utilisant MockRestServiceServer :

@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("//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); } } 

Dans l'extrait de code précédent, nous avons utilisé des méthodes statiques de MockRestRequestMatchers et MockRestResponseCreators pour définir l'attente et la réponse pour l'appel REST de manière claire et lisible:

import static org.springframework.test.web.client.match.MockRestRequestMatchers.*; import static org.springframework.test.web.client.response.MockRestResponseCreators.*;

Nous devons garder à l'esprit que le RestTemplate dans la classe de test doit être la même instance que celle utilisée dans la classe EmployeeService . Pour nous en assurer, nous avons défini un bean RestTemplate dans la configuration de printemps et câblé automatiquement l'instance à la fois en test et en implémentation:

@Bean public RestTemplate restTemplate() { return new RestTemplate(); }

L'utilisation d'un MockRestServiceServer est très utile lorsque nous écrivons nos tests d'intégration et n'avons besoin que de simuler des appels HTTP externes.

4. Conclusion

Dans ce bref article, nous avons discuté de quelques options efficaces pour se moquer des appels d'API REST externes via HTTP lors de l'écriture de tests unitaires.

Le code source de l'article ci-dessus est disponible à l'adresse over sur GitHub.