我正在尝试在集成测试中使用模拟,但运气不佳。我正在使用Spring 3.1.1和Mockito 1.9.0,情况如下:
@Component
public class ClassToTest {
@Resource
private Dependency dependency;
}
和
@Component
public class Dependency {
@Resource
private NestedDependency nestedDependency;
}
现在,我想使用 Spring 的 JavaConfig 对 ClassToTest 进行集成测试。这是我尝试过的,但它不起作用:
@Test
@ContextConfiguration
public class ClassToTestIntegrationTest {
@Resource
private ClassToTest classToTest;
@Resource
private Dependency mockDependency;
@Test
public void someTest() {
verify(mockDependency).doStuff();
// other Mockito magic...
}
@Configuration
static class Config {
@Bean
public ClassToTest classToTest() {
return new ClassToTest();
}
@Bean
public Dependency dependency() {
return Mockito.mock(Dependency.class);
}
}
}
我简化了我的设置,使问题更容易理解。实际上,我有更多的依赖项,只想模拟其中一些 - 其他的都是真实的,基于从我的 prod @Configuration 类导入的配置。
最终发生的事情是我得到一个NoSuchBeanDefinitionException,说应用程序上下文中没有NestedDependency 类型的 bean。我不明白这一点 - 我以为 Spring 会收到 Mockito 嘲笑的依赖实例,甚至不看自动接线它。由于这不起作用,我最终不得不模拟我的整个对象图 - 这完全违背了嘲笑的意义!
提前感谢任何帮助!
我遇到了同样的问题,我找到了另一种解决方案。当 Spring 实例化你所有的 bean 时,它会检查它是否是一个 Mockito Mock,在这种情况下,我返回 false 作为注入属性。要使用它,只需在 Spring 上下文中注入它
代码如下:
public class MockBeanFactory extends InstantiationAwareBeanPostProcessorAdapter {
private static final MockUtil mockUtil = new MockUtil();
public MockBeanFactory() {
super();
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
return !mockUtil.isMock(bean);
}
}
Mockito在模拟类时所做的是它使用cglib创建一个子类,该子类具有一些花哨的名称,例如:Dependency$EnhancerByMockito
(IIRC)。您可能知道,子类从其父类继承字段:
@Component
public class Dependency {
@Resource
private NestedDependency nestedDependency;
}
public class Dependency$EnhancerByMockito extends Dependency{
//...
}
这意味着 Spring 在呈现模拟时仍然会看到基类中的字段。您可以执行的操作:
使用接口,这将导致 Mockito 使用动态代理而不是 CGLIB 生成的类
模拟
NestedDependency
- 我知道它只会将问题进一步级联禁用测试的
@Resource
注释扫描