I am trying to write unit test for a validator class that I have. So within my UniqueEmailValidator class, I injected a @Service component to check if it exist.
@AllArgsConstructor public class UniqueEmailValidator implements ConstraintValidator<UniqueEmail, String> { private final AccountService accountService; @Override public void initialize(final UniqueEmail constraintAnnotation) { } @Override public boolean isValid(final String email, final ConstraintValidatorContext context) { return !this.accountService.findByEmail(email).isPresent(); } } @Documented @Target({TYPE, FIELD, ANNOTATION_TYPE}) @Retention(RUNTIME) @Constraint(validatedBy = UniqueEmailValidator.class) public @interface UniqueEmail { String message() default "{com.x.x.validator.UniqueEmail.message}"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
And I tried to write unit test for this constraint validator.
@RunWith(SpringRunner.class) @DataJpaTest public class AccountValidatorTest { private static Validator validator; @BeforeClass public static void setUp() { ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); validator = factory.getValidator(); } @Autowired private AccountService accountService; @Test public void shouldDetectDuplicatedEmailAddress() { User user = new User(); // Setters omit // accountRepository.save(user); Set<ConstraintViolation<AccountRegistrationForm>> violations = validator.validate(user); assertEquals(1, violations.size()); } }
How do I initialize the AccountService within the Validator class? It seem like it wasn’t injected, hence, the null exception. Here’s the trace.
javax.validation.ValidationException: HV000064: Unable to instantiate ConstraintValidator: com.x.x.validator.UniqueEmailValidator. at org.hibernate.validator.internal.util.privilegedactions.NewInstance.run(NewInstance.java:43) at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorFactoryImpl.run(ConstraintValidatorFactoryImpl.java:43) at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorFactoryImpl.getInstance(ConstraintValidatorFactoryImpl.java:28) at org.hibernate.validator.internal.engine.constraintvalidation.ClassBasedValidatorDescriptor.newInstance(ClassBasedValidatorDescriptor.java:65) at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager.createAndInitializeValidator(ConstraintValidatorManager.java:184) at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager.getInitializedValidator(ConstraintValidatorManager.java:136) at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.getInitializedConstraintValidator(ConstraintTree.java:148) at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.getInitializedConstraintValidator(ConstraintTree.java:124) at org.hibernate.validator.internal.engine.constraintvalidation.SimpleConstraintTree.validateConstraints(SimpleConstraintTree.java:55) at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.validateConstraints(ConstraintTree.java:73) at org.hibernate.validator.internal.metadata.core.MetaConstraint.doValidateConstraint(MetaConstraint.java:127) at org.hibernate.validator.internal.metadata.core.MetaConstraint.validateConstraint(MetaConstraint.java:120) at org.hibernate.validator.internal.engine.ValidatorImpl.validateMetaConstraint(ValidatorImpl.java:533) at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForSingleDefaultGroupElement(ValidatorImpl.java:496) at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForDefaultGroup(ValidatorImpl.java:465) at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForCurrentGroup(ValidatorImpl.java:430) at org.hibernate.validator.internal.engine.ValidatorImpl.validateInContext(ValidatorImpl.java:380) at org.hibernate.validator.internal.engine.ValidatorImpl.validate(ValidatorImpl.java:169) at com.x.x.AccountValidatorTest.shouldDetectDuplicatedEmailAddress(AccountValidatorTest.java:95) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:73) at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:83) at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75) at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86) at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:538) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:760) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:460) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:206) Caused by: java.lang.InstantiationException: com.x.x.validator.UniqueEmailValidator at java.lang.Class.newInstance(Unknown Source) at org.hibernate.validator.internal.util.privilegedactions.NewInstance.run(NewInstance.java:40) ... 50 more Caused by: java.lang.NoSuchMethodException: com.x.x.validator.UniqueEmailValidator.<init>() at java.lang.Class.getConstructor0(Unknown Source) ... 52 more
Thanks.
Advertisement
Answer
The actual problem is deep down in the stack-trace that you’ve provided:
Caused by: java.lang.NoSuchMethodException: com.x.x.validator.UniqueEmailValidator.<init>() at java.lang.Class.getConstructor0(Unknown Source) ... 52 more
This error message is thrown because there is some code that is trying to instantiate the UniqueEmailValidator
class constructor without any parameters. The problem will be resolved by adding a default constructor to this class:
public class UniqueEmailValidator implements ConstraintValidator<UniqueEmail, String> { public UniqueEmailValidator() { } ... }
Hope this helps!