Spring-boot: Method Validation doesn't work in Tests using MockMvc on SpringBoot version 1.5.0.BUILD-SNAPSHOT

Created on 7 Dec 2016  路  8Comments  路  Source: spring-projects/spring-boot

I wanted to use bean-validation for parameters of a @RestController method, as mentioned in #6228

I am using SpringBoot version 1.5.0.BUILD-SNAPSHOT and wanted to use method validation by adding a @Validated annotation on my controller and then constraints on my method.

@RestController
@Validated
public class HelloController {

    @RequestMapping("/")
    public String index() {
        return "Greetings from Spring Boot!";
    }

    @RequestMapping(value = "/{uid}", method = RequestMethod.GET)
    public String userById(@PathVariable @Size(max = 12) final String uid) {
        return "Hello :"+uid;
    }

    @ExceptionHandler(value = {ConstraintViolationException.class})
    @ResponseStatus(value = HttpStatus.BAD_REQUEST)
    public String handleValidationFailure(ConstraintViolationException ex) {
        StringBuilder messages = new StringBuilder();
        for (ConstraintViolation<?> violation : ex.getConstraintViolations()) {
            messages.append(violation.getMessage() + "\n");
        }
        return messages.toString();
    }

The validation works when I start up my service but my test in MockMvc fails against expected behavior of throwing a Constraint Violation exception when a constraint is violated.

The below test should fail due to violation of size constraint since I've set @Size(max = 12)

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = Application.class)
@WebAppConfiguration
@ActiveProfiles(profiles = "test")
public class HelloControllerTest {

    @Autowired
    private WebApplicationContext webApplicationContext;

    private MockMvc mockMvc;

    @Before
    public void setUp() throws Exception {
        mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
    }
    @Test
    public void getUserException() throws Exception {
        mockMvc.perform(get("/123222333322223"))
            .andExpect(status().isOk())
            .andExpect(content().string(equalToIgnoringCase("Hello :123222333322223")));
    }
}

My pom.xml file looks like

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.springframework</groupId>
    <artifactId>gs-spring-boot</artifactId>
    <version>0.1.0</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.0.BUILD-SNAPSHOT</version>
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
            <version>1.5.0.BUILD-SNAPSHOT</version>
        </dependency>
    </dependencies>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

    <repositories>
        <repository>
            <id>spring-snapshots</id>
            <name>Spring Snapshots</name>
            <url>https://repo.spring.io/libs-snapshot</url>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </repository>
    </repositories>

</project>

I am working off the sample Spring boot project from https://github.com/spring-guides/gs-spring-boot.git

enhancement

Most helpful comment

Validation is not enabled by default by @WebMvcTest (slice tests switch off auto-config and only enables a few of them explicitly). I guess we could add it to the list for @WebMvcTest.

All 8 comments

Validation is not enabled by default by @WebMvcTest (slice tests switch off auto-config and only enables a few of them explicitly). I guess we could add it to the list for @WebMvcTest.

Hello, I am solving the very same issue, but your answer isn't very descriptive to me. May I ask for final solution or more concrete hints how to solve the issue? Thanks

@maruskak this issue is resolved so Validation is auto-configured with WebMvcTest as of 1.5

@maruskak You can also add LocalValidatorFactoryBean and maven dependency by yourself.

    @Bean
    public LocalValidatorFactoryBean localValidatorFactoryBean() {
        return new LocalValidatorFactoryBean();
    }

Adds dependency

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

        <dependency>
            <groupId>org.glassfish.web</groupId>
            <artifactId>javax.el</artifactId>
            <version>2.2.4</version>
            <scope>test</scope>
        </dependency>

@ericxu131 there is a validation starter and no need to provide versions in the pom directly.

i am facing the same issue. it is not fixed yet ? am using Spring BOOT 1.5.10 RELEASE

@selvaebi We believe was fixed in 1.5.0.RC1 by commit d8d5950 on Dec 15, 2016. If you're still having trouble please open a new issue and provides a sample application that shows the problem.

If you add following snippet it should work as it worked for me as well.

@Before
    public void setup() throws Exception {
        this.mockMvc = standaloneSetup(screeningApiResources)
                .setControllerAdvice(new CustomExceptionHandler(), new ConstraintViolationsHandler())
                .build();
    }
Was this page helpful?
0 / 5 - 0 ratings