Se moquer d’un RestTemplate au printemps

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 quelquesoptions avec les applications Spring.

In this quick tutorial, we’ll look at just a couple of ways of mocking such calls performed only through a RestTemplate.

Nous allons commencer à tester avec Mockito, une bibliothèque de simulation 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 deMockito

Nous pourrions utiliser Mockito pour nous moquer du selRestTemplate . Avec cette approche, tester notre service serait aussi simple que n'importe quel autretest involving mocking.

Supposons que nous ayons une simple classeEmployeeService, 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("http://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(
            “http://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 facticeRestTemplate en utilisant l'annotation@Mock.

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

Enfin, dans la méthode de test, nous avons défini le comportement de notre simulation en utilisantMockito’s when/then support.

3. Utilisation du test de printemps

Le module Spring Test comprend un serveur simulé nomméMockRestServiceServer.With this approach, we configure the server to return a particular object when a specific request is dispatched through our RestTemplate instance. Enfin, nous pouvonsverify() sur cette instance de serveur, que toutes les attentes aient été satisfaites ou non.

MockRestServiceServer fonctionne en fait en interceptant les appels d'API HTTP à l'aide d'unMockClientHttpRequestFactory. Sur la base de notre configuration, il crée une liste des demandes attendues et des réponses correspondantes. Lorsque l'instanceRestTemplate 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 degetEmployee() en utilisantMockRestServiceServer:

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

Dans l'extrait de code précédent, nous avons utilisé des méthodes statiques de inMockRestRequestMatchers etMockRestResponseCreators 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 lesRestTemplate dans la classe de test doivent être la même instance que celle utilisée dans la classeEmployeeService. Pour ce faire, 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'unMockRestServiceServer 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 présenté quelques options efficaces pour mocker les appels d’API REST externes via HTTP lors de l’écriture de tests unitaires.

Le code source de l'article ci-dessus est disponibleover on GitHub.