Eine RestTemplate im Frühling verspotten

Verspotten einer RestTemplate im Frühjahr

1. Einführung

Häufig sind wir mit Anwendungen konfrontiert, die eine Art Webanforderung ausführen. Wenn es darum geht, dieses Verhalten zu testen, haben wir einigeoptions mit Spring-Apps.

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

Wir werden mit Mockito testen, einer beliebten Spottbibliothek. Anschließend verwenden wir Spring Test, mit dem wir einen Mechanismus zum Erstellen eines Mock-Servers zum Definieren der Serverinteraktionen bereitstellen können.

2. Verwenden vonMockito

Wir könnten Mockito verwenden, um dasRestTemplate -Salz zusammen zu verspotten. Mit diesem Ansatz wäre das Testen unseres Service so einfach wie jedes anderetest involving mocking.

Nehmen wir an, wir haben eine einfacheEmployeeService-Klasse, die Mitarbeiterdetails über HTTP abruft:

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

Implementieren wir unseren Test für den vorherigen Code: __

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

In der obigen JUnit-Testklasse haben wir Mockito zuerst gebeten, eine Dummy-Instanz vonRestTemplatemit der Annotation von@Mockzu erstellen.

Dann haben wir die Instanz vonEmployeeServicemit@InjectMocks kommentiert, um die Dummy-Instanz in sie zu injizieren.

Schließlich haben wir in der Testmethode das Verhalten unseres Mocks mitMockito’s when/then support definiert.

3. Federtest verwenden

Das Spring-Testmodul enthält einen Mock-Server mit dem NamenMockRestServiceServer.With this approach, we configure the server to return a particular object when a specific request is dispatched through our RestTemplate instance.. Schließlich können wirverify() auf dieser Serverinstanz festlegen, ob alle Erwartungen erfüllt wurden oder nicht.

MockRestServiceServer funktioniert tatsächlich, indem die HTTP-API-Aufrufe mitMockClientHttpRequestFactory abgefangen werden. Basierend auf unserer Konfiguration wird eine Liste der erwarteten Anforderungen und der entsprechenden Antworten erstellt. Wenn die Instanz vonRestTemplatedie API aufruft, schlägt sie die Anforderung in ihrer Liste der Erwartungen nach und gibt die entsprechende Antwort zurück.

Somit entfällt die Notwendigkeit, einen HTTP-Server an einem anderen Port zum Senden von Scheinantworten auszuführen.

Erstellen wir einen einfachen Test für dasselbe Beispiel vongetEmployee()mitMockRestServiceServer:

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

Im vorherigen Snippet haben wir statische Methoden aus inMockRestRequestMatchers undMockRestResponseCreators verwendet, um die Erwartung und Antwort für den REST-Aufruf klar und lesbar zu definieren:

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

Wir sollten bedenken, dassRestTemplate in der Testklasse dieselbe Instanz sein sollte, die in der KlasseEmployeeService verwendet wird. Um dies zu gewährleisten, haben wir in der Frühjahrskonfiguration eine RestTemplate-Bean definiert und die Instanz in Test und Implementierung automatisch verkabelt:

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

Die Verwendung vonMockRestServiceServer ist sehr nützlich, wenn wir unsere Integrationstests schreiben und nur externe HTTP-Aufrufe verspotten müssen.

4. Fazit

In diesem kurzen Artikel haben wir einige effektive Optionen zum Verspotten der externen REST-API-Aufrufe über HTTP beim Schreiben von Komponententests erörtert.

Der Quellcode für den obigen Artikel istover on GitHub verfügbar.