Spring boot: как написать модульный тестовый пример для шаблона удаления остатка - PullRequest
0 голосов
/ 01 августа 2020

Я пытаюсь написать модульный тестовый пример для класса HttpHandler, у которого есть вызов шаблона отдыха для удаления. Я создал класс usercontroller для вызова resttemplate, чтобы проверить функциональность sendDelete в классе HttpHandler. Может ли кто-нибудь помочь мне понять, как правильно написать пример модульного теста для метода sendDelete в классе HtttpHandler?

У меня есть класс HttpHandler. У него есть функция sendDelete, где он вызывает resttemplate.exchange метод

@Service
public class HttpHandler {
public <T,R> ResponseEntity<Void> sendDelete(String url, HttpHeaders httpHeaders, R requestBody, Class<T> responseClass) {
        //create an instance of rest template
        RestTemplate restTemplate = new RestTemplate();
        HttpEntity<R> entity = new HttpEntity<R>(requestBody, httpHeaders);
        logger.info("DELETE request to " + url + " with body: " + JsonUtil.jsonizeExcludeNulls(requestBody));
        //make an HTTP DELETE request with headers
        ResponseEntity<Void> response = restTemplate.exchange(url, HttpMethod.DELETE, entity, Void.class);
        logger.info("DELETE" + url + ": " + JsonUtil.jsonize(response));
        return response;
    }
}

Я использую junit5. Ниже приведен пример модульного теста для метода sendDelete в указанном выше классе:

@LocalServerPort
    private int port;

    private String baseUrl;

    @Autowired
    private HttpHandler httpHandler;

    @BeforeEach
    public void setBaseUrl(){
        this.baseUrl = "http://localhost:"+ port + "/users";
    }

@Test
    public void testSuccessDeleteUserById() throws Exception{
        this.baseUrl = baseUrl + "/1";
        //create headers
        HttpHeaders httpHeaders = new HttpHeaders();

        //set content type
        httpHeaders.setContentType(MediaType.APPLICATION_JSON);
        httpHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));

        //make an HTTP DELETE request with headers

        ResponseEntity<Void> actual = httpHandler.sendDelete(baseUrl, httpHeaders, null, Void.class);
        assertEquals(404, actual.getStatusCodeValue());
    }

Ниже представлен класс пользовательского контроллера

@RestController
public class UserController {
@DeleteMapping("/users/{userId}")
    public ResponseEntity<Void> deleteUser(@PathVariable("userId") int userId){
        return new ResponseEntity<Void>(HttpStatus.NOT_FOUND);
    }
}

Спасибо за ваше время!

1 Ответ

0 голосов
/ 01 августа 2020

Есть два способа сделать это.

  1. Mocking RestTemplate. Для этого сначала нужно сделать RestTemplate полем и внедрить его через конструктор (или любым другим способом). Это позволяет вам внедрить фиктивный объект. Остальное - просто насмешка.

  2. Вы можете использовать MockWebServer . Таким образом, вам не нужно ничего менять. Это просто веб-сервер, на который ваш метод отправит запрос. После завершения вызова метода вы можете получить доступ к записанному запросу и выполнить некоторые проверки.

Вот грубый пример. Если у вас будет много таких тестов, вы можете переместить инициализацию веб-сервера в метод @BeforeEach, а уничтожение - в метод @AfterEach.

public class HttpHandlerTest {

    private final HttpHandler handler = new HttpHandler();

    @Test
    @SneakyThrows
    public void testDelete() {
        MockWebServer mockWebServer = new MockWebServer();
        mockWebServer.start(9889);

        mockWebServer.enqueue(
                new MockResponse().setResponseCode(200)
        );

        String url = "http://localhost:9889";
        Hello hello = new Hello("hello world");

        final ResponseEntity<Void> entity = handler.sendDelete(url, null, hello, Hello.class);

        assertNotNull(entity);
        assertEquals(200, entity.getStatusCode().value());

        final RecordedRequest recordedRequest = mockWebServer.takeRequest();

        assertEquals("DELETE", recordedRequest.getMethod());
        
        mockWebServer.close();
    }

}

// just an example class to use as a payload
class Hello {
    String text;

    public Hello() {
    }

    public Hello(String text) {
        this.text = text;
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }
}

Примечание. Даже если вы не выберете первое решение, я рекомендую вам отказаться от инициализации RestTemplate для каждого запроса. Лучше вместо этого использовать WebClient. Если вы это сделаете, первое решение больше не будет работать, а второе останется нетронутым.

...