【问题标题】:Initialising mock in new objects在新对象中初始化模拟
【发布时间】:2017-07-06 21:34:20
【问题描述】:

我的班级不能自动装配 UserService - 它会抛出 NullPointerException。我想找到一种方法来测试 UserValidator 类。我不知道如何在 ExistingValidationRule 类中注入模拟。

public class ExistingValidationRule implements RegistrationRule<User> {
@Autowired
private UserService service;

@Override
public void validate(User user, Errors errors) {

    service.find(user, errors);
}
}


@Component
public class UserValidator implements Validator {

    @Override
    public void validate(Object o, Errors errors) {
        User user = (User) o;
        rules.add(new ExistingValidationRule());

        for(RegistrationRule<User> rule : rules){
            rule.validate(user, errors);
        }
    }
}

public class UserValidatorTest {
@InjectMocks
private UserValidator userValidator;

@InjectMocks
private ExistingValidationRule existingValidationRule;

@Mock
private UserService service;

@Before
public void setup() {
    MockitoAnnotations.initMocks(this);
}
@Test
    public void testValidUser() throws Exception{

        userValidator.validate(createdUser,errors);
}

【问题讨论】:

  • 如果你使用new创建Spring bean实例,它们就不再是Spring bean实例,因此不能被Spring自动装配,它甚至无法知道这个实例是否存在。将 ExistingValidationRule 实例自动装配到 UserValidator 中。
  • 当你的大部分问题都被否决时,你就是在做一些惹恼很多人的事情。或许没有功课就是答案。

标签: java spring unit-testing mockito


【解决方案1】:
class UserValidator  
// if all roles that you need are spring beans- then do autowired then by super type
@Autowired 
privete Collection<RegistrationRule> roles ;

@Override
public void validate(Object o, Errors errors) {
    User user = (User) o;

    // all spring-bean configured validators were autowired 
    for(RegistrationRule<User> rule : rules){ 
        rule.validate(user, errors);
    }
}

@Component
public class UserValidator implements Validator {
    //if rules was created before
    @Autowired
    public void setExistingValidationRule(ExistingValidationRule existingValidationRule){
        rules.add(existingValidationRule);
    }

@Override
public void validate(Object o, Errors errors) {
    User user = (User) o;

    for(RegistrationRule<User> rule : rules){
        rule.validate(user, errors);
    }
}

并尽量避免在方法 validate() 中添加新的职责——比如添加新的验证器。方法 validate 应该只做验证,仅此而已

【讨论】:

    【解决方案2】:

    @Autowired 是一个 Spring 注释,除非您使用 Spring 测试运行器运行单元测试,否则它不会做任何事情。

    但是,Mockito 的@InjectMocks 只会用 Mocks 填充您的字段,只要您提供构造函数来访问这些字段。请尝试以下操作:

    public class ExistingValidationRule implements RegistrationRule<User> {
        @Autowired
        private UserService service;
    
        public ExistingValidationRule(UserService service) {
            this.service = service;
        }
    
        public ExistingValidationRule() {
        }
    
        @Override
        public void validate(User user, Errors errors) {
    
            service.find(user, errors);
        }
    }
    

    我添加了第二个空构造函数来让 Spring 快乐。第一个应该可以为您的单元测试解决问题。

    测试愉快!

    【讨论】:

      猜你喜欢
      • 2013-03-07
      • 1970-01-01
      • 2022-01-19
      • 2019-06-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-10
      • 2020-10-13
      相关资源
      最近更新 更多