Как правильно издеваться над моим модульным тестом RestTemplate?

#java #spring-boot #junit #mockito #resttemplate

Вопрос:

Мой текущий модульный тест, использующий RestTemplate для достижения конечной точки GET, содержит множество жестко закодированных значений. Я хотел бы знать, есть ли лучший подход, высмеивающий ценности, и как это сделать. В настоящее время это выглядит так:

 @RunWith(MockitoJUnitRunner.class)
public class CarServiceTest {

    private final String uri = "https://cars.com/cars";
    private final String token = "xxx";

    private List<Car> carList;
    private Cars testCars;

    @Mock
    private RestTemplate restTemplate;

    @InjectMocks
    private CarService carService;

    @BeforeAll
    void init() {
        carList = new ArrayList<>(Arrays.asList(new Car("car1")));
        testCars = new Cars(carList);
    }

    @Test
    public void test_getCars() {

        HttpHeaders headers = new HttpHeaders();
        headers.setBearerAuth(token);
        headers.setAccept(List.of(MediaType.APPLICATION_JSON));

        Mockito.when(restTemplate.exchange(
                                    RequestEntity.get(new URI(uri)).headers(headers).build(),
                                    Cars.class))
            .thenReturn(new ResponseEntity(testCars, HttpStatus.OK));

        Cars returnedCars = carService.getCars();

        // assertion
        Assert.assertEquals(testCars, returnedCars);

        // verify
        verify(restTemplate).exchange(RequestEntity
                                        .get(new URI(uri)).headers(headers).build(),
                                         Cars.class);
        verifyNoMoreInteractions(restTemplate);
    }
}
 

Я ищу предложения о том, как улучшить инициализацию/издевательство над объектами, используемыми в тесте. (В настоящее время я использую реальный URL-адрес и токен в тестах)

Ответ №1:

Вы можете использовать сервер MockRestServiceServer.

 RestTemplate restTemplate = new RestTemplate();
MockRestServiceServer server = MockRestServiceServer.bindTo(restTemplate).build();

server.expect(MockRestRequestMatchers.requestTo(uri))
    .andExpect(requestTo(uri))
    .andExpect(method(HttpMethod.GET))
    .andRespond(withSuccess(new ObjectMapper()
        .writeValueAsString(cars), MediaType.APPLICATION_JSON));


HttpHeaders headers = new HttpHeaders();
headers.setBearerAuth(token);
headers.setAccept(List.of(MediaType.APPLICATION_JSON));

restTemplate.exchange(RequestEntity.get(new URI(uri)).headers(headers).build(), Cars.class))

server.verify();
 

Вы можете настроить заглушку, которая вам нужна, а также убедиться, что вызовы, которые вы ожидали, действительно произошли в нескольких строках кода и намного более понятны ИМО.

Комментарии:

1. Какие аннотации вам нужно использовать при объявлении переменных?

2. Это полностью зависит от вашей тестовой среды , но если вы говорите о таких аннотациях, как @Mock , например, они вам больше не нужны, так как spring выполняет всю обработку и проверку для вас. Вы можете прочитать документацию, связанную с ответом, чтобы узнать больше.