我已经阅读了很多关于如何模拟Spring的bean及其自动连接字段的文章。但是我无法找到有关自动装配的bean列表的信息。
具体问题
我是一个名为FormValidatorManager
的班级。该类循环遍历几个实现IFormValidator
的验证器。
@Component
public class FormValidatorManager implements IValidatorManager {
@Autowired
private List<IFormValidator> validators;
@Override
public final IFieldError validate(ColumnDTO columnToValidate, String sentValue) {
String loweredColName = columnToValidate.getName().toLowerCase();
IFieldError errorField = new FieldError(loweredColName);
for (IEsmFormValidator validator : validators) {
List<String> errrorsFound = validator.validate(columnToValidate, sentValue);
//les erreurs ne doivent pas être cumulées.
if(CollectionUtils.isNotEmpty(errrorsFound)){
errorField.addErrors(errrorsFound);
break;
}
}
return errorField;
}
}
我想测试这个课程。但我无法找到模仿validators
财产的方法。
我尝试了什么
由于IFormValidators
是单身,我试图模拟这些bean的几个实例,希望它们反映在FormValidatorManager.validators
中,但没有成功。
然后,我尝试创建一个注释为IFormValidators
的{{1}}列表。通过手动启动@Mock
,我希望List
注入创建的列表。那仍然没有成功。
这是我的最后一次尝试:
initMocks()
NPE被抛入@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:spring/test-validator-context.xml"})
public class FormValidatorManagerTest {
@Mock
private RegexValidator regexValidator;
@Mock
private FormNotNullValidator notNullValidator;
@Mock
private FormDataTypeValidator dataValidator;
@InjectMocks
private FormValidatorManager validatorManager;
@Mock
private List<IEsmFormValidator> validators = new ArrayList<IEsmFormValidator>();
@Mock
private ColumnDTO columnDTO;
@Before
public void init() {
validators.add(notNullValidator);
validators.add(regexValidator);
validators.add(dataValidator);
MockitoAnnotations.initMocks(this);
Mockito.when(columnDTO.getTitle()).thenReturn("Mock title");
Mockito.when(columnDTO.getName()).thenReturn("Mock name");
}
@Test
public void testNoErrorFound(){
mockValidator(notNullValidator, new ArrayList<String>());
mockValidator(regexValidator, new ArrayList<String>());
mockValidator(dataValidator, new ArrayList<String>());
IFieldError fieldErrors = validatorManager.validate(columnDTO, "Not null value");
Assert.assertEquals(0, fieldErrors.getErrors().size());
verifyNumberOfValidateCalls(regexValidator, Mockito.atMost(1));
verifyNumberOfValidateCalls(dataValidator, Mockito.atMost(1));
verifyNumberOfValidateCalls(notNullValidator, Mockito.atMost(1));
}
private void mockValidator(IFormValidator validator, List<String> listToReturn){
Mockito.when(validator.validate(Mockito.any(ColumnDTO.class), Mockito.anyString())).thenReturn( listToReturn );
}
private void verifyNumberOfValidateCalls(IFormValidator validator, VerificationMode verifMode){
Mockito.verify(validator, verifMode).validate(Mockito.any(ColumnDTO.class), Mockito.anyString());
}
}
,我将被嘲笑。不应该调用具体的实现。
这导致了一种非常糟糕的行为,因为我对该类的一些测试是误报,而其他测试则完全失败。
我试图弄清楚如何模拟自动连接的bean列表,同时仍然可以模拟特定的实现。
您是否有开始解决方案的想法?
此致
答案 0 :(得分:15)
我终于明白了......
有时,提出问题可以让您更好地解决问题:p
问题是我在验证之前将验证器链接到列表。然后验证器为null,并且在调用MockitAnnotations.initMocks(this)
时无法更新引用。
此外,为了避免List
上的迭代器问题,我不得不使用@Spy
而不是@Mock
。
以下是最终解决方案:
@Mock
private EsmRegexValidator regexValidator;
@Mock
private EsmFormNotNullValidator notNullValidator;
@Mock
private EsmFormDataTypeValidator dataValidator;
@InjectMocks
private EsmFormValidatorManager validatorManager;
@Spy
private List<IEsmFormValidator> validators = new ArrayList<IEsmFormValidator>();
@Mock
private ColumnDTO columnDTO;
@Before
public void init() {
MockitoAnnotations.initMocks(this);
validators.add(notNullValidator);
validators.add(regexValidator);
validators.add(dataValidator);
Mockito.when(columnDTO.getTitle()).thenReturn("Mock title");
Mockito.when(columnDTO.getName()).thenReturn("Mock name");
}