Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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).

like image 812
Luís Soares Avatar asked Jun 28 '16 16:06

Luís Soares


People also ask

How do you test annotations?

Annotation Type Test. The Test annotation tells JUnit that the public void method to which it is attached can be run as a test case. To run the method, JUnit first constructs a fresh instance of the class then invokes the annotated method. Any exceptions thrown by the test will be reported by JUnit as a failure.

What does the @valid annotation do?

The @Valid annotation is a key feature of Bean Validation, as it allows to validate object graphs with a single call to the validator. To make use of it all fields that should be recursively checked should be annotated with @Valid .

What is the difference between @valid and @validated?

The @Valid annotation ensures the validation of the whole object. Importantly, it performs the validation of the whole object graph. However, this creates issues for scenarios needing only partial validation. On the other hand, we can use @Validated for group validation, including the above partial validation.


1 Answers

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

like image 89
Vlad Dinulescu Avatar answered Oct 02 '22 22:10

Vlad Dinulescu