How to check class validation annotations using JUnit?

I need to check validation annotations , but it looks like they are not working. I am not sure if JUnit is correct. Currently, the test will be passed, but as you can see, the specified email address is incorrect.

Junit

public static void testContactSuccess() { Contact contact = new Contact(); contact.setEmail("Jackyahoo.com"); contact.setName("Jack"); System.err.println(contact); } 

Class for testing

 public class Contact { @NotNull @Size(min = 1, max = 10) String name; @NotNull @Pattern(regexp="[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\." +"[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@" +"(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?", message="{invalid.email}") String email; @Digits(fraction = 0, integer = 10) @Size(min = 10, max = 10) String phone; getters and setters } 
+7
java junit
source share
6 answers

another answer saying that “annotations do nothing on their own, you need to use Validator to process the object” is correct, however the answer is not enough work instructions on how to do this using an instance of Validator, which for me was that I really wanted to.

Hibernate-validator is the reference implementation of such a validator. You can use this pretty cleanly:

 import static org.junit.Assert.assertFalse; import java.util.Set; import javax.validation.ConstraintViolation; import javax.validation.Validation; import javax.validation.Validator; import javax.validation.ValidatorFactory; import org.junit.Assert; import org.junit.Before; import org.junit.Test; public class ContactValidationTest { private static Validator validator; @Before public void setUp() { ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); validator = factory.getValidator(); } @Test public void testContactSuccess() { // I'd name the test to something like // invalidEmailShouldFailValidation() Contact contact = new Contact(); contact.setEmail("Jackyahoo.com"); contact.setName("Jack"); Set<ConstraintViolation<Contact>> violations = validator.validate(contact); assertFalse(violations.isEmpty()); } } 

This assumes that you are implementing the validator and junit implementation as dependencies.

An example of dependencies using Maven pom:

 <dependency> <groupId>org.hibernate</groupId> <version>5.2.4.Final</version> <artifactId>hibernate-validator</artifactId> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> 
+12
source share

Annotations do nothing on their own, you need to use Validator to process the object.

Your test should run some code like this

  Configuration<?> configuration = Validation .byDefaultProvider() .providerResolver( new MyResolverStrategy() ) <== this is where is gets tricky .configure(); ValidatorFactory factory = configuration.buildValidatorFactory(); Contact contact = new Contact(); contact.setEmail("Jackyahoo.com"); contact.setName("Jack"); factory.getValidator().validate(contact); <== this normally gets run in the background by whatever framework you are using 

However, the difficulty that you encounter here is all the interfaces, you will need implementations for testing. You can implement it yourself or find it to use.

However, the question you want to ask yourself is what are you trying to verify? That the hibernate validator works the way it should? or that your regex is correct?

If it were me, I would suggest that the validator works (i.e., someone else checked this) and focuses on the regular expression. Which will include a little reflection

 public void emailRegex(String email,boolean validates){ Field field = Contact.class.getDeclaredField("email"); javax.validation.constraints.Pattern[] annotations = field.getAnnotationsByType(javax.validation.constraints.Pattern.class); assertEquals(email.matches(annotations[0].regexp()),validates); } 

then you can define your testMethods, which are actual unit tests

 @Test public void testInvalidEmail() throws NoSuchFieldException { emailRegex("Jackyahoo.com", false); } @Test public void testValidEmail() throws NoSuchFieldException { emailRegex(" jack@yahoo.com ", true); } @Test public void testNoUpperCase() throws NoSuchFieldException { emailRegex(" Jack@yahoo.com ", false); } 
+3
source share

There are two things you need to check:

Validation rule configured correctly

Validation rules can be verified, as others advise, by creating a validator object and calling it manually:

 Set violations = validator.validate(contact); assertFalse(violations.isEmpty()); 

With this you should check all possible cases - there can be dozens of them (and in this case there should be several).

Validation is done using frameworks

In your case, you test it with Hibernate, so there should be a test that initializes it and runs some Hibernate operations. Please note that for this you need to check only one rejection rule for one field - this will be enough. You do not need to check all the rules again. An example could be:

 @Test(expected = ConstraintViolationException.class) public void validationIsInvokedBeforeSavingContact() { Contact contact = Contact.random(); contact.setEmail(invalidEmail()); contactsDao.save(contact) session.flush(); // or entityManager.flush(); } 

Note. Remember to run flush() . If you work with UUID or sequences as an identifier generation strategy, then INSERT will not be cleared, if you save() , it will be delayed until the end.

All this is part of creating a test pyramid - you can find more here .

+1
source share

eg:

 public class Test { @Autowired private Validator validator; public void testContactSuccess() { Contact contact = new Contact(); contact.setEmail("Jackyahoo.com"); contact.setName("Jack"); System.err.println(contact); Set<ConstraintViolation<Contact>> violations = validator.validate(contact); assertTrue(violations.isEmpty()); } } 

and you also need to add a bean to your .xml context, for example:

 <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"> </bean> 
0
source share

Here is my way to unit test my objects with fields annotated with some javax.validation.constraints restrictions.
I will give an example with Java 8, the JPA entity, Spring Boot and JUnit 5, but the general idea is the same regardless of context and frameworks:
We have a nominal scenario in which all fields are correctly evaluated and, as a rule, multiple error scenarios when one or more fields are incorrectly evaluated.

Validating field validation is not particularly difficult. But since we have many fields to test, the tests can be complicated, we can forget some cases by introducing side effects in the tests between the two cases to check or just introducing duplication. I will talk about how to avoid this.

In the OP code, we assume that 3 fields have a NotNull constraint. I think that under three different constraints, the pattern and its meaning are less noticeable.

I wrote unit test first for a nominal scenario:

 import org.junit.jupiter.api.Test; @Test public void persist() throws Exception { Contact contact = createValidContact(); // action contactRepository.save(contact); entityManager.flush(); entityManager.clear(); // assertion on the id for example ... } 

I am extracting the code to create a valid contact in the method, as it will be useful without nominal cases:

 private Contact createValidContact(){ Contact contact = new Contact(); contact.setEmail("Jackyahoo.com"); contact.setName("Jack"); contact.setPhone("33999999"); return contact; } 

Now I am writing a @parameterizedTest as the source source of a @MethodSource :

 import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; import javax.validation.ConstraintViolationException; @ParameterizedTest @MethodSource("persist_fails_with_constraintViolation_fixture") void persist_fails_with_constraintViolation(Contact contact ) { assertThrows(ConstraintViolationException.class, () -> { contactRepository.save(contact); entityManager.flush(); }); } 

To compile / run @parameterizedTest , consider adding the required dependency, which is not included in the junit-jupiter-api dependency:

 <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-params</artifactId> <version>${junit-jupiter.version}</version> <scope>test</scope> </dependency> 

In the bind method to create invalid contacts, the idea is simple. For each case, I create a new valid contact object, and I incorrectly set only the field for checking the corresponding one.
Thus, I guarantee that there is no side effect between the cases and that each case causes the expected exception of validation, since without the set field, the actual contact is successfully saved.

 private static Stream<Contact> persist_fails_with_constraintViolation_fixture() { Contact contactWithNullName = createValidContact(); contactWithNullName.setName(null); Contact contactWithNullEmail = createValidContact(); contactWithNullEmail.setEmail(null); Contact contactWithNullPhone = createValidContact(); contactWithNullPhone.setPhone(null); return Stream.of(contactWithNullName, contactWithNullEmail, contactWithNullPhone); } 

Here is the complete test code:

 import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; import javax.validation.ConstraintViolationException; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager; import org.springframework.test.context.junit.jupiter.SpringExtension; @DataJpaTest @ExtendWith(SpringExtension.class) public class ContactRepositoryTest { @Autowired private TestEntityManager entityManager; @Autowired private ContactRepository contactRepository; @BeforeEach public void setup() { entityManager.clear(); } @Test public void persist() throws Exception { Contact contact = createValidContact(); // action contactRepository.save(contact); entityManager.flush(); entityManager.clear(); // assertion on the id for example ... } @ParameterizedTest @MethodSource("persist_fails_with_constraintViolation_fixture") void persist_fails_with_constraintViolation(Contact contact ) { assertThrows(ConstraintViolationException.class, () -> { contactRepository.save(contact); entityManager.flush(); }); } private static Stream<Contact> persist_fails_with_constraintViolation_fixture() { Contact contactWithNullName = createValidContact(); contactWithNullName.setName(null); Contact contactWithNullEmail = createValidContact(); contactWithNullEmail.setEmail(null); Contact contactWithNullPhone = createValidContact(); contactWithNullPhone.setPhone(null); return Stream.of(contactWithNullName, contactWithNullEmail, contactWithNullPhone); } } 
0
source share

I think that checks will work after calling predefined methods that are usually performed by containers, mostly not immediately after calling the setters of the object. By the link with the documentation that you shared:

<P → By default, the Persistence provider will automatically validate on objects with constant fields or properties annotated with Bean validation restrictions immediately after the PrePersist, PreUpdate, and PreRemove life cycle events.
-one
source share

All Articles