Spring MVC Test with Validation JSR-303/349: Locale или accept-language не работают при тестировании

Я работаю с Spring Framework 4.3.3

У меня следующая ситуация для @Controller либо для POST, либо PUT

Например, для POST у меня есть следующее:

@PostMapping(value="/save",
             consumes=MediaType.APPLICATION_FORM_URLENCODED_VALUE,
             produces=MediaType.TEXT_HTML_VALUE)
public String saveOne(@Validated @ModelAttribute Persona persona,
        BindingResult result,
        RedirectAttributes redirectAttributes){

    logger.info("saveOne: {}", persona.toString());

    if(result.hasErrors()){
        logger.error("# Errors: {}", result.getErrorCount());
        logger.error("result: {}", result.toString());
        return "persona/saveOne";
    }

    personaRestController.saveOne(persona);

    redirectAttributes.addFlashAttribute("message", "process.successful");
    return "redirect:/message";
}

Приложение работает так, как ожидается, с помощью Web Form этого @PostMapping либо сохраняет / сохраняет данные, либо проверяет данные и, если они недействительны, та же веб-форма отображается с сообщениями об ошибках для каждого поля на основе i18n, например English, Spanish и Portuguese. Это связано с JSR-439

О конфигурации инфраструктуры конфигурации Java у меня есть следующее:

@Bean
public LocaleChangeInterceptor localeChangeInterceptor(){
        LocaleChangeInterceptor localeChangeInterceptor=new LocaleChangeInterceptor();
        localeChangeInterceptor.setParamName("language");
        //localeChangeInterceptor.setHttpMethods("post", "put");
        return localeChangeInterceptor;
}

@Bean(name="localeResolver")
public LocaleResolver cookieLocaleResolver(){
        CookieLocaleResolver cookieLocaleResolver = new CookieLocaleResolver();
        cookieLocaleResolver.setCookieName("language");
        cookieLocaleResolver.setDefaultLocale(new Locale("en","US"));
        return cookieLocaleResolver;
}

А также

@EnableWebMvc
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {

...

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(localeChangeInterceptorConfig.localeChangeInterceptor());
    }

Проблема в Spring MVC Test. Имею следующее:

@Before
public void setUp(){
    mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}

...

@Test
public void saveOneHtmlPostInvalidMaxTest() throws Exception {

    logger.info("saveOneHtmlPostInvalidMaxTest");

    resultActions = mockMvc.perform(post(url)
                .contentType(MediaType.APPLICATION_FORM_URLENCODED)
                .locale(locale)
                .header("accept-language", locale.toString())
                .header("language", locale.toString())
                .param("id", personaInvalidMax.getId())
                .param("nombre", personaInvalidMax.getNombre())
                .param("apellido", personaInvalidMax.getApellido())
                ....
                .andDo(print());

Примечание:

                .locale(locale)
                .header("accept-language", locale.toString())
                .header("language", locale.toString())

Даже когда некоторые из них не имеют смысла, они есть, потому что я пытаюсь разрешить следующую ситуацию:

Контроль проверки со стороны сервера работает так, как ожидается, до определенного момента.

Первый

Я могу подтвердить .andDo(print()) методом, что MockHttpServletRequest печатает

Заголовки = {Content-Type = [application / x-www-form-urlencoded], accept-language = [pt_BR], language = [pt_BR]}

Соблюдайте pt_BR

Второй

@PostMapping, который содержит:

if(result.hasErrors()){
    logger.error("# Errors: {}", result.getErrorCount());
    logger.error("result: {}", result.toString());
    return "persona/saveOne";
}

Печать ...

7370 [Тестовый работник] ОШИБКА PersonaSaveOneController - результат: org.springframework.validation.BeanPropertyBindingResult: 4 ошибки Ошибка поля в объекте 'persona' в поле 'id': отклоненное значение [0]; коды [Size.persona.id, Size.id, Size.java.lang.String, Size]; аргументы [org.springframework.context.support.DefaultMessageSourceResolvable: коды [persona.id, id]; аргументы []; сообщение по умолчанию [id], 3,3]; сообщение по умолчанию [размер поля должен быть от 3 до 3]

Соблюдайте default message [id],3,3]; default message [The size for the field must be between 3 and 3]

Тут две проблемы:

  • locale или accept-language игнорируются
  • Сообщения об ошибках всегда печатаются на английском языке.

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

Опять же, это работает, когда я использую Web Form напрямую, но не через Test. Я предполагаю, что существует внутренний компонент Spring, который работает через production и не был определен для Testing

Итак, что нужно для реализации этого подхода?

Кстати: со следующим (см. Я использую classpath:), кроме того, мой .properties файл находится в src/main/resources

@Bean(name="messageSource")
public ReloadableResourceBundleMessageSource reloadableResourceBundleMessageSource() {
        ReloadableResourceBundleMessageSource resource = new ReloadableResourceBundleMessageSource();
        resource.setBasenames(...
"classpath:/com/manuel/jordan/validation/validation");
        resource.setDefaultEncoding("UTF-8");
        return resource;
}

Мои @Test методы, работающие с Rest, отлично работают с показом и возвратом сообщения об ошибке в соответствии с определенными Locale или accept-language (доступ к MessageSource происходит на стороне сервера и отлично работает с предыдущей конфигурацией). Просто не работает для non-Rest контроллеров


person Manuel Jordan    schedule 24.09.2016    source источник
comment
Возможный дубликат Spring messageSource работает в JSP, а не работает в jUnit test   -  person rorschach    schedule 24.09.2016
comment
Я скажу, что не дублируется, код работает в продакшене, но не работает так, как ожидается при тестировании.   -  person Manuel Jordan    schedule 25.09.2016
comment
Точно так же, как код в другом потоке.   -  person rorschach    schedule 25.09.2016
comment
Вы предполагаете, что это о ReloadableResourceBundleMessageSource?, Верно? У меня есть другой тест на Rest, и он отлично работает. Проблема в том, что сервер приложений не распознает Locale или accept-language, отправленные из теста. Все мои .properties файлы упоминаются через classpath:   -  person Manuel Jordan    schedule 25.09.2016