Как написать тест для контроллера, который включает в себя ошибки / BindingResult? - PullRequest
1 голос
/ 05 апреля 2019

Я работаю над простым веб-сайтом, используя Spring Boot и Spring MVC, и столкнулся со сценарием, для которого мне не удалось написать тест.Как вы проверяете, как контроллер работает с Errors, которые влияют на пользовательский интерфейс, но не включены в ModelAndView?

У меня были проблемы с отображением сообщений об ошибках в моей форме HTML, и послея обнаружил большое разочарование, потому что я перезаписывал объект Form, а затем возвращал его как объект в ModelAndView.

Это код вопроса

@PostMapping
ModelAndView processPost(@Valid IdAndAmountForm idAndAmountForm, Errors errors) {
    if (errors.hasErrors()) {
        var beer = service.findBeerById(idAndAmountForm.getId());
        return new ModelAndView("beerView")
                .addObject("beer", beer)
                .addObject("idAndAmountForm", idAndAmountForm);
    } else {
        cart.add(idAndAmountForm);
        return new ModelAndView("redirect:/cart");
    }
}

Он работает / ведет себя как ожидалось, заполняя span соответствующим сообщением при удалении проверки HTML.

    <form th:action="@{/beer}" th:object="${idAndAmountForm}" method="post">
        <label>
            Amount
            <span th:errors="*{amount}"></span>
            <input th:field="*{amount}" type="number" min="1" required>
        </label>

Моя ошибка была в строке 7 контроллера, где у меня ранее было .addObject("idAndAmountForm", new IdAndAmountForm()); Не было ошибок, связанных с новой формой, поэтому сообщения об ошибках не отображались.Или это то, что, я думаю, произошло.

Теперь, как я мог написать тест, который обнаружил бы это ошибочное поведение?Я потратил некоторое время на анализ Model, отыскивая сообщения об ошибках, которые, как я знал, каким-то образом передавались в шаблон Thymeleaf, прежде чем прийти к выводу, что сообщения об ошибках обрабатывались Spring отдельно. Этот ответ помог мне увидеть, что это был BindingResult или Errors объект, который я хотел проверить в своем тесте.Однако, это не часть возвращаемого значения любого метода, который я написал.

Полагаю, я мог бы попытаться написать тест для ViewResolver или любого другого автоматически генерируемого объекта, промежуточного между моим контроллером и моим шаблоном, или я мог бы разделить мой класс контроллера, чтобы позволить моему тестовому классу получить доступ к ошибкам.Оба кажутся плохими идеями.Текущее решение состоит в том, чтобы считать сценарий слишком большим усилием для тестирования, но я не хочу верить, что это непроверяемое в принципе .

1 Ответ

0 голосов
/ 05 апреля 2019

Вы можете написать тест контроллера с помощью Spring, чтобы достичь желаемого. Spring MVC Test Framework предоставляет действительно хороший и легкий для чтения свободный API, который можно использовать для тестирования всевозможных сценариев в MVC с использованием MockMvc .

Для вашего случая использования, при тестировании ошибок результата привязки атрибутов модели, вы, вероятно, напишете тест, который использует MockMvcResultMatchers и статическую status () , модель ( ) , view () , flash () и т. Д.

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

mockMvc.perform(post(YOUR_URL).contentType(APPLICATION_FORM_URLENCODED)
    .param(...)
    .param(...)
    .andExpect(model().hasErrors())
    .andExpect(model().attributeHasFieldErrors(FORM_MODEL_NAME, "field"))
    .andExpect(model().attributeHasFieldErrorCode(FORM_MODEL_NAME, "anotherfield", "error")
    .andExpect(view().name(YOUR_VIEW));

Подробнее о Spring MVC Test Framework здесь: https://docs.spring.io/spring/docs/current/spring-framework-reference/testing.html#spring-mvc-test-framework

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...