我试图在我的集成测试中使用模拟并且没有太多运气。我使用的是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嘲笑的Dependency实例,甚至不会看自动装配它。由于这不起作用,我最终不得不模拟我的整个对象图 - 这完全打败了嘲弄点!
提前感谢您的帮助!
答案 0 :(得分:4)
我有同样的问题,我找到了另一个解决方案。 当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);
}
}
答案 1 :(得分:2)
Mockito在模拟类时所做的是它使用cglib创建一个子类,其中有一些奇特的名称,如:Dependency$EnhancerByMockito
(IIRC)。您可能知道,子类从其父级继承字段:
@Component
public class Dependency {
@Resource
private NestedDependency nestedDependency;
}
public class Dependency$EnhancerByMockito extends Dependency{
//...
}
这意味着当使用mock时,Spring仍会在基类中看到该字段。你能做什么:
使用接口,这将导致Mockito使用动态代理而不是CGLIB生成的类
模拟NestedDependency
- 我知道它会将问题进一步级联
禁用@Resource
测试的注释扫描