Search code examples
javaspringjunitspring-boothibernate-validator

How to test if @Valid annotation is working?


I have the following unit test:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = {EqualblogApplication.class})
@WebAppConfiguration
@TestPropertySource("classpath:application-test.properties")
public class PostServiceTest {
  // ...

  @Test(expected = ConstraintViolationException.class)
  public void testInvalidTitle() {
       postService.save(new Post());  // no title
  }
}

The code for save in PostService is:

public Post save(@Valid Post post) {
    return postRepository.save(post);
}

The Post class is marked with @NotNull in most fields.

The problem is: no validation exception is thrown.

However, this happens only in testing. Using the application normally runs the validation and throws the exception.

Note: I would like to do it automatically (on save) and not by manually validating and then saving (since it's more realistic).


Solution

  • This solution works with Spring 5. It should work with Spring 4 as well. (I've tested it on Spring 5 and SpringBoot 2.0.0).

    There are three things that have to be there:

    1. in the test class, provide a bean for method validation (PostServiceTest in your example)

    Like this:

    @TestConfiguration
    static class TestContextConfiguration {
       @Bean
       public MethodValidationPostProcessor bean() {
          return new MethodValidationPostProcessor();
       }
    }
    
    1. in the class that has @Valid annotations on method, you also need to annotate it with @Validated (org.springframework.validation.annotation.Validated) on the class level!

    Like this:

    @Validated
    class PostService {
       public Post save(@Valid Post post) {
           return postRepository.save(post);
       }
    }
    
    1. You have to have a Bean Validation 1.1 provider (such as Hibernate Validator 5.x) in the classpath. The actual provider will be autodetected by Spring and automatically adapted.

    More details in MethodValidationPostProcessor documentation

    Hope that helps