Знущання над RestTemplate навесні

1. Вступ

Часто ми стикаємось із програмами, які виконують певний веб-запит. Що стосується тестування такої поведінки, у нас є кілька варіантів з програмами Spring.

У цьому короткому навчальному посібнику ми розглянемо лише кілька способів знущання над такими дзвінками, здійсненими лише за допомогою RestTemplate .

Ми почнемо тестування з Mockito, популярної бібліотеки для насмішок. Потім ми використаємо Spring Test, який надає нам механізм створення макетного сервера для визначення взаємодії сервера.

2. Використання Mockito

Ми могли б використовувати Mockito, щоб взагалі знущатися над RestTemplate . При такому підході тестування нашої послуги було б таким же простим, як і будь-яке інше тестування, що передбачає глузування.

Припустимо, у нас є простий клас EmployeeService , який отримує дані про співробітників через 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; } } 

Давайте реалізуємо наш тест для попереднього коду:

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

У наведеному вище тестовому класі JUnit, ми попросили перший Mockito створити фіктивний RestTemplate екземпляр з допомогою @Mock анотації.

Потім ми анотували екземпляр EmployeeService @InjectMocks для введення в нього фіктивного екземпляра.

Нарешті, у методі тестування ми визначили поведінку нашого макета, використовуючи підтримку Mockito, коли / тоді.

3. Використання весняного тесту

TheМодуль Spring Test включає макетний сервер з ім’ям MockRestServiceServer. За допомогою цього підходу ми налаштовуємо сервер на повернення певного об’єкта, коли конкретний запит надсилається через наш екземпляр RestTemplate . Нарешті, ми можемо перевірити () на цьому екземплярі сервера, чи всі очікування були виконані чи ні.

MockRestServiceServer насправді працює, перехоплюючи виклики API HTTP за допомогою MockClientHttpRequestFactory . На основі нашої конфігурації він створює список очікуваних запитів та відповідних відповідей. Коли екземпляр RestTemplate викликає API, він шукає запит у своєму списку очікувань і повертає відповідну відповідь.

Таким чином, це позбавляє від необхідності запускати HTTP-сервер у будь-якому іншому порту для надсилання фіктивних відповідей.

Давайте створимо простий тест для того самого прикладу getEfficiee (), використовуючи 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); } } 

У попередньому фрагменті ми використовували статичні методи з MockRestRequestMatchers та MockRestResponseCreators, щоб чітко і зрозуміло визначити очікування та відповідь на виклик REST:

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

Слід пам’ятати, що RestTemplate у тестовому класі повинен бути таким самим екземпляром, як і в класі EmployeeService . Щоб забезпечити це, ми визначили компонент RestTemplate у весняній конфігурації та автоматично підключили екземпляр як у тесті, так і в реалізації:

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

Використання MockRestServiceServer дуже корисно, коли ми пишемо наші тести інтеграції і маємо лише знущатися із зовнішніх HTTP-дзвінків.

4. Висновок

У цій короткій статті ми обговорили кілька ефективних варіантів знущання над зовнішніми викликами REST API через HTTP під час написання модульних тестів.

Вихідний код для вищевказаної статті доступний на GitHub.