Подтвердить что ты не робот

Spring mockMvc не рассматривает проверку в моем тесте

Я пытаюсь настроить интеграционное тестирование с помощью mockMvc, и у меня есть проблема с ним. Действительно, spring не включает никакой аннотации проверки.
Для большей точности я помещаю код класса Controller, который можно протестировать:

@Controller
public class UserRegisterController {
    private final Log log = LogFactory.getLog(UserRegisterController.class);

    private UserManager userManager;

    @Autowired
    public UserRegisterController(UserManager userManager){
        this.userManager = userManager;
    }

    /**
     * Register a new user.
     *
     */
    @RequestMapping(value = "/User/Register", 
            method = RequestMethod.GET
    )
    public @ResponseBody SimpleMessage submitForm(
            @Valid UserInfoNew userInfo,
            BindingResult result
    ){
        if(log.isInfoEnabled())
            log.info("Execute UserRegister action");
        SimpleMessage message;

        try {
            if(result.hasErrors()){
                if(log.isFatalEnabled())
                    log.fatal("Parameters sent by user for registering aren't conform. Errors are : "
                            + result.getFieldErrors().toString());
                throw new Exception(result.getFieldErrors().toString());
            }

            User user = new User();
            user.setLogin(userInfo.getLogin());
            user.setFamilyName(userInfo.getFamilyName());
            user.setFirstName(userInfo.getFirstName());
            user.setPassword(userInfo.getPassword());
            user.setDateBirthday(userInfo.getDateBirthday());
            user.setEmail(userInfo.getEmail());
            user.setMobile(userInfo.getMobile());
            user.setAddress(userInfo.getAddress());

            userManager.createUser(user);

            User newUser = userManager.findLastUserCreated();

            //Change to null some sensitive or useless return parameters
            newUser.setPassword(null);
            //

            message = new SimpleMessage(null, newUser);
        } catch (Exception e) {
            if(log.isErrorEnabled())
                log.error("A problem of type : " + e.getClass() 
                        + " has occured, with message : " + e.getMessage());
            message = new SimpleMessage(
                            new SimpleException(e.getClass(), e.getMessage()), null);
        }

        return message;
    }
}

Затем объект с аннотацией hibernate и javax для проверки:

public abstract class UserParameters {

    @Min(1)
    protected Long id;

    @Length(min=4, max=20)
    protected String login;

    @Length(min=4, max=20)
    protected String familyName;

    @Length(min=4, max=20)
    protected String firstName;

    @Pattern(regexp="^.*(?=.{8,20})(?=.*[a-z]+)(?=.*[a-z]+)(?=.*[A-Z]+)(?=.*[A-Z]+)"
            + "(?=.*[0-9]+)(?=.*[0-9]+)(?=.*[@$%*#]+).*$")
    protected String password;

    @Past
    protected Calendar dateBirthday;

    @Email
    @Length(max=255)
    protected String email;

    @Pattern(regexp="^[0]{1}[67]{1}[ .-]{1}[0-9]{2}[ .-]{1}"
            + "[0-9]{2}[ .-]{1}[0-9]{2}[ .-]{1}[0-9]{2}$")
    protected String mobile;

    @Length(max=255)
    protected String address;

    protected Calendar dateCreation;

    protected Calendar dateLastAccess;
}

public class UserInfoNew extends UserParameters  implements Serializable{   

    private static final long serialVersionUID = 4427131414801253777L;

    @NotBlank
    public String getLogin() {
            return login;
    }   
    public void setLogin(String Login) {
            this.login = Login;
    }

    public String getFamilyName() {
            return familyName;
    }   
    public void setFamilyName(String Name) {
            this.familyName = Name;
    }

    public String getFirstName() {
            return firstName;
    }   
    public void setFirstName(String FirstName) {
            this.firstName = FirstName;
    }

    @NotBlank
    public String getPassword() {
            return password;
    }   
    public void setPassword(String Password){
        this.password = Password;
    }

    public Calendar getDateBirthday() {
        return dateBirthday;
    }
    public void setDateBirthday(Calendar strBirthDay) {     
        this.dateBirthday = strBirthDay;
    }

    public String getEmail() {
        return email;
    }
    public void setEmail(String Mail) {
        this.email = Mail;
    }

    @NotBlank
    public String getMobile() {
        return mobile;
    }
    public void setMobile(String Mobile) {
        this.mobile = Mobile;
    }

    public String getAddress() {
        return address;
    }   
    public void setAddress(String Address) {
        this.address = Address;
    }
}

и класс, который реализует тест:

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(classes = {
        WebInit_Test.class,
        AppConfig_Test.class,
        WebConfig_1.class,
        WebConfig_2.class,
        WebSocketConfig.class
})
public class UserControllersTest {

    @Autowired
    private WebApplicationContext wac;

    private MockMvc mockMvc;

    @Before
    public void setUp() throws Exception {

        this.mockMvc = MockMvcBuilders.webAppContextSetup(wac)
                        .alwaysExpect(status().isOk())
                           .alwaysExpect(content().contentType("application/json;charset=UTF-8"))
                    .build();
}

@Test
public void userRegister() throws Exception {
    //doesn't consider @Valid during test
    mockMvc.perform(get("/User/Register?Login=A&Password=aaAA&Mobile=0134320285")
            .contentType(MediaType.ALL)
    )
            .andExpect(jsonPath("error").exists());


}
}

Когда я запускаю тест, элемент ошибки не существует, тогда как логин, пароль и мобильный телефон не могут быть подтверждены аннотацией javax и hibernate. Более того, когда я пытаюсь отправить URL-адрес на localhost, выполняется проверка, и новый пользователь не сохраняется в базе данных.
Как вы можете видеть, я использую конфигурацию java-кода для своего веб-уровня, я полагаю, что проблема исходит от него. Кроме того, я загружаю проект из команды spring в github (link: github.com/spring-projects/spring-mvc-showcase), в котором подробно описаны все виды тестов, которые мы можем сделать с помощью mockmvc. Единица проверки (в пакете" org.springframework.samples.mvc.validation") не работает с моей конфигурацией проекта, но очень хорошо с ней в исходной конфигурации.

Чтобы закончить, я отправляю вам все классы конфигурации

@Configuration
public class WebInit_Test extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class<?>[] { AppConfig_Test.class };
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class<?>[] { WebConfig_1.class, WebConfig_2.class, WebSocketConfig.class };
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }

    @Override
    protected void customizeRegistration(Dynamic registration) {
        registration.setInitParameter("dispatchOptionsRequest", "true");
        registration.setLoadOnStartup(1);
    }
}

@Configuration
@ImportResource({
    "classpath:/applicationContext-dao.xml",
    "classpath:/applicationContext-datasource-test.xml",
    "classpath:/applicationContext-service.xml"
})
public class AppConfig_Test {

}

@Configuration
@EnableWebMvc
@ComponentScan(
        basePackages = "project.web",
        excludeFilters = @ComponentScan.Filter(type= FilterType.ANNOTATION, value = Configuration.class)
)
public class WebConfig_1 extends WebMvcConfigurationSupport {

    @Autowired
    private FormattingConversionServiceFactoryBean conversionService;

    @Bean
    @Override
    public FormattingConversionService mvcConversionService() {
        FormattingConversionService conversionService = this.conversionService.getObject();
        addFormatters(conversionService);
        return conversionService;
    }
}

@Configuration
public class WebConfig_2 extends WebMvcConfigurerAdapter{

    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
            configurer.enable();
    }

    /**
     * Configure output mapping, see 
     * {@link http://stackoverflow.com/info/4823358/spring-configure-responsebody-json-format} 
     * for more information
     * 
     * @param converters
     *          a list of {@link HttpMessageConverter<?>}
     */
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        final MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        final ObjectMapper objectMapper = new ObjectMapper();        
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        converter.setObjectMapper(objectMapper);
        converters.add(converter);
        super.configureMessageConverters(converters);
    }
}

@Configuration
//@EnableScheduling
@ComponentScan(
        basePackages="project.web",
        excludeFilters = @ComponentScan.Filter(type= FilterType.ANNOTATION, value = Configuration.class)
)
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/friendship", "/message", "/journey", "/information");
        config.setApplicationDestinationPrefixes("/app");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/client").withSockJS();
    }
}

Спасибо за вашу помощь.

4b9b3361

Ответ 1

Хорошо, я только что нашел то, что отвечает за то, что проверка не рассматривалась mockmvc. Это просто плохая зависимость в моем помпе:  

Я использовал

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>5.1.0.Final</version>
</dependency>

и когда я заменил его на

<dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
    <version>1.0.0.GA</version>
</dependency>
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>4.1.0.Final</version>
</dependency>

тестовая работа просто прекрасна! Проблема решена, но мне интересно, почему проблема исходит из этой части. hibernate-validator 5.1.0.Final включают проверку javax в транзитивной зависимости, поэтому обычно эта проблема никогда бы не появилась.

Ответ 2

У меня такая же проблема, после обновления validator до 5.1.0.Final. Приложение работает отлично, но тесты REST не (аннотация @Valid не учитывается вообще). Я решил проблему с добавлением одной дополнительной зависимости только для тестов:

   <dependency>
     <groupId>javax.el</groupId>
     <artifactId>javax.el-api</artifactId>
     <version>2.2.4</version>
     <scope>test</scope>
  </dependency>

Ответ 3

Если вы используете версию спящего режима 5.4.1. Final просто добавьте ниже зависимости для вашего теста.

<dependency>
    <groupId>org.glassfish</groupId>
    <artifactId>javax.el</artifactId>
    <version>3.0.0</version>
</dependency>

Эта зависимость является "предоставленной" зависимостью. Вы можете найти соответствующую зависимость для версии hibernate на сайте maven. https://mvnrepository.com/artifact/org.hibernate/hibernate-validator/5.4.1.Final

Например, если вы используете версию 5.4.1, перейдите по ссылке выше и проверьте наличие зависимостей и используйте ее.