У меня похожий случай, который работает в Java (вы можете переписать в Kotlin). Пожалуйста, попробуйте:
определить новый bean-компонент в вашем классе конфигурации, аннотированный @Configuration:
@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
return new MethodValidationPostProcessor();
}
, аннотируйте свой контроллер с помощью:
@RestController
@Validated
Затем вы можете проверить вас класс с:
postHours(@RequestBody LinkedHashMap<String, @Valid Hours> hours)
----- МОДИФИКАЦИЯ ДЛЯ ПРЕДОСТАВЛЕНИЯ ПОЛНОГО ПРИМЕРА -----
Вы можете использовать этот полный пример. Я использую: spring-boot-starter-web 2.2.6 с lombok.
Вот класс для проверки:
@Data
public class Foo {
@Max(value = 3)
private Integer count;
}
Контроллер:
@RestController
@Validated
public class FooController {
@PostMapping("/validate")
public String validate(@RequestBody LinkedHashMap<String, List<@Valid Foo>> foos) {
return "foo";
}
}
Класс конфигурации:
@Configuration
public class AppConfig {
@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
return new MethodValidationPostProcessor();
}
}
Рекомендация контроллера (для отправки исключения как json):
@ControllerAdvice
public class CustomResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {
@Data
@AllArgsConstructor
class ApiError {
private HttpStatus status;
private String message;
private List<String> errors;
}
@ExceptionHandler({ ConstraintViolationException.class })
public ResponseEntity<Object> handleConstraintViolation(ConstraintViolationException ex, WebRequest request) {
List<String> errors = new ArrayList<>();
for (ConstraintViolation<?> violation : ex.getConstraintViolations()) {
errors.add(violation.getRootBeanClass().getName() + " " +
violation.getPropertyPath() + ": " + violation.getMessage());
}
ApiError apiError = new ApiError(HttpStatus.BAD_REQUEST, ex.getLocalizedMessage(), errors);
return new ResponseEntity<>(apiError, new HttpHeaders(), apiError.getStatus());
}
}
Класс теста:
@WebMvcTest(FooController.class)
public class FooControllerTest {
@Autowired
private MockMvc mockMvc;
@Autowired
private ObjectMapper objectMapper;
@Test
public void test() throws Exception {
LinkedHashMap<String, Foo> foos = new LinkedHashMap<>();
Foo foo = new Foo();
foo.setCount(4);
foos.put("foo", foo);
this.mockMvc.perform(post("/validate")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(bars)))
.andExpect(status().isBadRequest())
.andExpect(content().string(containsString("validate.foos[foo].<map value>[0].count: must be less than or equal to 3")));
}
}
Модульный тест показывает, что проверка внутри связанного хэш-карты работает.