如何使用Junit和Mockito测试Spring验证器



我有一个Spring验证器:

@Component
public class AddClientAccountValidator implements Validator {
    @Autowired
    private ValidatorUtils validatorUtils;
    @Override
    public boolean supports(Class<?> clazz) {
        return UserDto.class.equals(clazz);
    }
    @Override
    public void validate(Object target, Errors errors) {
        UserDto user = (UserDto) target;
        validatorUtils.setParam(errors, user);
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "username", "username.required");
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "password", "password.required");
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "confirmPassword",
                "confirmPassword.required");
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "firstName", "firstName.required");
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "lastName", "lastName.required");
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "personalId", "personalId.required");
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "city", "city.required");
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "address", "address.required");
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "email", "email.required");
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "phone", "phone.required");
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "contribution", "contribution.required");
        validatorUtils.validateAddClientAccount();
    }
}

在上面的Validator已经注入到ValidatorUtils类:

@Component
class ValidatorUtils {
    @Autowired
    private PersonalIdValidator personalIdValidator;
    private Errors errors;
    private UserDto user;
    void setParam(Errors errors, UserDto user) {
        this.errors = errors;
        this.user = user;
    }
    void validateAddClientAccount() {
        validateAccount();
        validContributionAccount();
    }
    private void validateAccount() {
        validUsername();
        validPassword();
        validFirstName();
        validLastName();
        validPersonalId();
        validCity();
        validAddress();
        validEmail();
        validPhone();
    }
    public void validateChangePassword() {
        validChangePassword();
    }
    private void validUsername() {
        if (!user.getUsername().isEmpty()) {
            String username = user.getUsername();
            if ((username.length() < 3) || (username.length() > 40)) {
                errors.rejectValue("username", "username.format");
            }
        }
    }
    private void validPassword() {
        if (!user.getPassword().isEmpty()) {
            String password = user.getPassword();
            if ((password.length() < 3) || (password.length() > 40)) {
                errors.rejectValue("password", "password.format");
            }
            if (!password.equals(user.getConfirmPassword())) {
                errors.rejectValue("confirmPassword", "password.confirm");
            }
        }
    }
    private void validFirstName() {
        if (!user.getFirstName().isEmpty()) {
            String firstName = user.getFirstName();
            String regex = "[A-ZŁ{1}]+[a-zł]+";
            boolean validFirstName = Pattern.matches(regex, firstName);
            if ((firstName.length() < 3) || (firstName.length() > 40) || !validFirstName) {
                errors.rejectValue("firstName", "firstName.format");
            }
        }
    }
    private void validLastName() {
        if (!user.getLastName().isEmpty()) {
            String lastName = user.getLastName();
            String regex = "[A-ZĆŁŚŻŹ{1}]+[a-ząćęłńóśżź]+";
            String regexWithTwoLastName = "[A-ZĆŁŚŻŹ{1}]+[a-ząćęłńóśżź]++[\s]+[A-ZĆŁŚŻŹ{1}]+[a-ząćęłńóśżź]+";
            boolean validLastName = Pattern.matches(regex, lastName);
            boolean validWithTwoLastName = Pattern.matches(regexWithTwoLastName, lastName);
            if ((lastName.length() < 3) || (lastName.length() > 40)
                    || (!validLastName && !validWithTwoLastName)) {
                errors.rejectValue("lastName", "lastName.format");
            }
        }
    }

这个类有更多的字段验证器,但我跳过了它。

我想测试我的Validator类使用Junit或最终mock。我写这个测试类:

    @RunWith(MockitoJUnitRunner.class)
public class AddClientAccValidatorTest {
    @InjectMocks
    private AddClientAccountValidator validator;
    @Mock
    private ValidatorUtils validatoUtils;
    private UserDto userDto;
    public Errors errors;
    @Before
    public void setUp() {
        UserDto userDto = new UserDto();
        errors = new BeanPropertyBindingResult(userDto, "userDto");
    }
    @Test
    public void testValidate() {
        validator.validate(userDto, errors);
        assertFalse(errors.hasErrors());
    }
}

但是当我运行测试时,我得到以下Failet跟踪:

java.lang.AssertionError
at org.junit.Assert.fail(Assert.java:86)
at org.junit.Assert.assertTrue(Assert.java:41)
at org.junit.Assert.assertFalse(Assert.java:64)
at org.junit.Assert.assertFalse(Assert.java:74)
at pl.piotr.ibank.validator.AddClientAccValidatorTest.testValidate(AddClientAccValidatorTest.java:67)
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.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
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.runners.ParentRunner.run(ParentRunner.java:363)
at org.mockito.internal.runners.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37)
at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

为什么我得到这个错误?我在这一行得到错误:

errors = new BeanPropertyBindingResult(userDto, "userDto");

我的第二个问题是我不能声明多个RunWith注释。当我添加:

@RunWith(MockitoJUnitRunner.class)

我不能使用@RunWith(Parameterized.class)参数化我的测试

如何解决?

有人能帮我吗?也许我的方法不好?用Junit测试Spring Validator的最佳方法是什么?

您可以在没有Mockito的情况下成功运行测试。下面的代码与Spring @Configuration类一起工作(需要Spring -test作为依赖项):

package foo.bar;
import static org.junit.Assert.assertFalse;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.AnnotationConfigContextLoader;
import org.springframework.validation.BeanPropertyBindingResult;
import org.springframework.validation.Errors;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader = AnnotationConfigContextLoader.class)
public class AddClientAccValidatorTest {
    @Configuration
    static class ContextConfiguration {
        @Bean
        public AddClientAccountValidator validator() {
            return new AddClientAccountValidator();
        }
        @Bean
        public ValidatorUtils validatorUtils() {
            return new ValidatorUtils();
        }
    }
    @Autowired
    private AddClientAccountValidator validator;
    private UserDto userDto;
    public Errors errors;
    @Before
    public void setUp() {
        userDto = new UserDto();
        userDto.setLastName("Doe");
        userDto.setFirstName("John");
        userDto.setUsername("username");
        userDto.setPhone("phone");
        userDto.setPassword("password");
        userDto.setConfirmedPassword("password");
        userDto.setEmail("email");
        userDto.setContribution("contribution");
        userDto.setAddress("address");
        userDto.setCity("city");
        userDto.setPersonalId("personalId");
        errors = new BeanPropertyBindingResult(userDto, "userDto");
    }
    @Test
    public void testValidate() {
        validator.validate(userDto, errors);
        assertFalse(errors.hasErrors());
    }
}

您不需要Mock任何东西。在验证时,我们需要要验证的对象和错误。创建一个对象,其中包含验证所需的字段和errors对象。例如,

@Test
public void shouldReturnErrorsWhenCustomObjectIsNull() {
    CustomValidator customValidator = new CustomValidator();
    Employee employee = new Employee();
    employee.setEmployeeFirstname("empName")

    Errors errors = new BeanPropertyBindingResult(employee, "employee");
    customValidator.validate(employee, errors);
    List<ObjectError> allErrors = errors.getAllErrors();
    assertTrue("Errors list size should not be null : ", allErrors.size() > 0);
    assertTrue(errors.hasErrors());
    assertNotNull( errors.getFieldError("empName") );
}

相关内容

  • 没有找到相关文章

最新更新