Verspotten einer RestTemplate im Frühjahr

1. Einleitung

Häufig finden wir uns mit Anwendungen wieder, die eine Art Webanforderung ausführen. Wenn Sie dieses Verhalten testen möchten, haben wir einige Optionen für Spring-Apps.

In diesem kurzen Tutorial sehen wir uns nur einige Möglichkeiten an, solche Aufrufe zu verspotten, die nur über eine RestTemplate ausgeführt werden .

Wir werden mit Mockito testen, einer beliebten Spottbibliothek. Dann verwenden wir Spring Test, der uns einen Mechanismus zum Erstellen eines Mock-Servers zum Definieren der Serverinteraktionen bietet.

2. Verwenden von Mockito

Wir könnten Mockito verwenden, um das RestTemplate insgesamt zu verspotten . Mit diesem Ansatz wäre das Testen unseres Service so einfach wie jeder andere Test, bei dem es um Spott geht.

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

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

Lassen Sie uns unseren Test für den vorherigen Code implementieren:

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

In der obigen JUnit- Testklasse haben wir Mockito zuerst gebeten, eine Dummy- RestTemplate- Instanz mithilfe der @ Mock- Annotation zu erstellen .

Anschließend haben wir die EmployeeService- Instanz mit @InjectMocks kommentiert , um die Dummy-Instanz in sie einzufügen .

Schließlich haben wir in der Testmethode das Verhalten unseres Mocks mithilfe von Mockitos Wann / Dann-Unterstützung definiert.

3. Federtest verwenden

DasDas Spring Test-Modul enthält einen Mock-Server namens MockRestServiceServer. Bei diesem Ansatz konfigurieren wir den Server so, dass er ein bestimmtes Objekt zurückgibt, wenn eine bestimmte Anforderung über unsere RestTemplate- Instanz gesendet wird . Schließlich können wir auf dieser Serverinstanz überprüfen () , ob alle Erwartungen erfüllt wurden oder nicht.

MockRestServiceServer funktioniert tatsächlich durch Abfangen der HTTP-API-Aufrufe mithilfe einer MockClientHttpRequestFactory . Basierend auf unserer Konfiguration wird eine Liste der erwarteten Anforderungen und entsprechenden Antworten erstellt. Wenn die RestTemplate- Instanz die 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 mit MockRestServiceServer einen einfachen Test für dasselbe getEmployee () -Beispiel :

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

Im vorherigen Snippet haben wir statische Methoden aus MockRestRequestMatchers und MockRestResponseCreators 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 berücksichtigen, dass das RestTemplate in der Testklasse dieselbe Instanz sein sollte, die in der EmployeeService- Klasse verwendet wird. Um dies sicherzustellen, haben wir in der Spring-Konfiguration eine RestTemplate-Bean definiert und die Instanz sowohl im Test als auch in der Implementierung automatisch verkabelt:

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

Die Verwendung eines MockRestServiceServers 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 erläutert.

Der Quellcode für den obigen Artikel ist auf GitHub verfügbar.