如何模拟自动装配的Spring bean列表?

时间:2015-10-23 12:27:12

标签: java spring unit-testing mockito autowired

我已经阅读了很多关于如何模拟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列表,同时仍然可以模拟特定的实现。

您是否有开始解决方案的想法?

此致

1 个答案:

答案 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");
}