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.