Это хорошая практика для модульного тестирования классов контроллера в Spring MVC - PullRequest
1 голос
/ 12 апреля 2019

Я использовал для модульного тестирования мои классы контроллера, как и любой другой нормальный класс Java.Я имею в виду без использования Spring's MockMvc.Но потом я понял, что таким образом я не смогу быть уверенным, что я правильно настроил конфигурацию MVC.Поэтому, если у меня есть контроллер, подобный этому:

@Restcontroller
@RequestMapping("/cars")
public class CarController{
    private CarService carService;
    public CarController (CarService service){this.carService = service};
    @GetMapping
    public List<Car> getCar(@RequestParam("filter") String filter){
       if(filter!=null && !filter.trim().equal("")){
          //omitted for brevity
       }
    }
}

, и если я тестирую его метод getCar напрямую, даже если тест пройден, это не будет означать, что с моим контроллером все в порядке.Поэтому вместо модульного тестирования я начал проводить интеграционное тестирование.Примерно так:

mockMvc.perform(get("/v1/cars?filter = Honda"))....  bla bla bla

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

1 Ответ

1 голос
/ 12 апреля 2019

Лично я никогда не находил полезными контроллеры модульного тестирования. В идеальном случае контроллер относительно тонкий, так как он вызывает только несколько методов служебных объектов и возвращает результат. Модульное тестирование IMO означало бы (пере) использование метода verify(). (То есть контроллер вызывал метод службы с правильными аргументами.)

Например, в моем случае хорошо написанный метод контроллера выглядит так:

@LoggingInfo
  @PostMapping(value = "/someRoute",
      produces = "application/json",
      consumes = "application/json")
  @ApiOperation(value = "Some description", response = SomeDTO.class)
  public @ResponseBody
  CompletableFuture<ResponseEntity> someControllerMethod(
      @Validated(ValidationSequence.class) @RequestBody SomeDTO someDTO) {

    return service
        .doSomething(someDTO)
        .thenApply((String var) -> ResponseEntity.ok(ResponseDTO.builder()
            .myField(Collections.singleton(var)).build()));
  }

В какой степени модульное тестирование этого метода увеличит ценность приложения?

Для меня переломным моментом стало использование интеграционных тестов. Вот и получается, что вся весенняя магия работает правильно, например:

  • Валидаторы, которые были вызваны аннотациями
  • Порядок (разных) валидаторов
  • Конвертеры (т.е. см. Джексона в действии)
  • Обработчики исключений (являются ли они исключениями, фактически обнаруженными аннотированными обработчиками исключений)

Надеюсь, это поможет.

...