복붙노트

[SPRING] Validator를 사용한 스프링 유닛 테스트 문제

SPRING

Validator를 사용한 스프링 유닛 테스트 문제

내가 가지고있는 검사기 클래스에 대한 단위 테스트를 작성하려고합니다. 그래서 내 UniqueEmailValidator 클래스 내에 @Service 컴포넌트가 삽입되어 있는지 확인합니다.

@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 {};
}

그리고이 제약 검사기에 대한 단위 테스트를 작성하려고했습니다.

@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 AccountRepository accountRepository;

    @Test
    public void shouldDetectDuplicatedEmailAddress() {

        User user = new User(); 
        // Setters omit

        // accountRepository.save(user);

        Set<ConstraintViolation<AccountRegistrationForm>> violations = validator.validate(user);

        assertEquals(1, violations.size());
    }

}

Validator 클래스 내에서 AccountService를 초기화하는 방법은 무엇입니까? 그것은 주입되지 않았던 것처럼 보입니다. 그러므로 null 예외입니다. 여기에 흔적이 있습니다.

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

감사.

해결법

  1. ==============================

    1.실제 문제는 제공 한 스택 추적에 깊이 관여합니다.

    실제 문제는 제공 한 스택 추적에 깊이 관여합니다.

    Caused by: java.lang.NoSuchMethodException: com.x.x.validator.UniqueEmailValidator.<init>()
    at java.lang.Class.getConstructor0(Unknown Source)
    ... 52 more
    

    매개 변수없이 UniqueEmailValidator 클래스 생성자를 인스턴스화하려고하는 코드가 있기 때문에이 오류 메시지가 발생합니다. 문제는이 클래스에 기본 생성자를 추가하여 해결할 수 있습니다.

    public class UniqueEmailValidator implements ConstraintValidator<UniqueEmail, String> {
        public UniqueEmailValidator() {
        }
        ...
    }
    

    희망이 도움이!

  2. ==============================

    2.기본이 아닌 논쟁의 public 생성자가 필요합니다. Validator에 Spring 구성 요소를 전달해야하는 경우 테스트시 문제가 발생할 수 있습니다.

    기본이 아닌 논쟁의 public 생성자가 필요합니다. Validator에 Spring 구성 요소를 전달해야하는 경우 테스트시 문제가 발생할 수 있습니다.

    나는 서비스를 보유하고 서비스를 제공하는 정적 메소드를 가진 컴포넌트를 가짐으로써 그것을 해결했다.

  3. from https://stackoverflow.com/questions/50104995/spring-unit-test-issue-with-validator by cc-by-sa and MIT license