我想将Mockito模拟对象注入到Spring (3+) bean中,以便使用JUnit进行单元测试。我的bean依赖项目前是通过在私有成员字段上使用@Autowired注释注入的。
我考虑过使用ReflectionTestUtils。setField,但是我希望注入的bean实例实际上是一个代理,因此没有声明目标类的私有成员字段。我不希望为依赖项创建公共setter,因为我将纯粹为了测试目的而修改我的接口。
我遵循了Spring社区提供的一些建议,但模拟没有被创建,自动连接失败:
<bean id="dao" class="org.mockito.Mockito" factory-method="mock">
<constructor-arg value="com.package.Dao" />
</bean>
我目前遇到的错误如下:
...
Caused by: org...NoSuchBeanDefinitionException:
No matching bean of type [com.package.Dao] found for dependency:
expected at least 1 bean which qualifies as autowire candidate for this dependency.
Dependency annotations: {
@org...Autowired(required=true),
@org...Qualifier(value=dao)
}
at org...DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(D...y.java:901)
at org...DefaultListableBeanFactory.doResolveDependency(D...y.java:770)
如果我将constructor-arg值设置为无效的值,那么在启动应用程序上下文时就不会出现错误。
更新-新的答案在这里:https://stackoverflow.com/a/19454282/411229。这个答案只适用于3.2之前的Spring版本。
我一直在寻找一个更明确的解决方案。这篇博客文章似乎涵盖了我的所有需求,并且不依赖于bean声明的顺序。这一切都要归功于Mattias Severson。http://www.jayway.com/2011/11/30/spring-integration-tests-part-i-creating-mock-objects/
基本上,实现一个FactoryBean
package com.jayway.springmock;
import org.mockito.Mockito;
import org.springframework.beans.factory.FactoryBean;
/**
* A {@link FactoryBean} for creating mocked beans based on Mockito so that they
* can be {@link @Autowired} into Spring test configurations.
*
* @author Mattias Severson, Jayway
*
* @see FactoryBean
* @see org.mockito.Mockito
*/
public class MockitoFactoryBean<T> implements FactoryBean<T> {
private Class<T> classToBeMocked;
/**
* Creates a Mockito mock instance of the provided class.
* @param classToBeMocked The class to be mocked.
*/
public MockitoFactoryBean(Class<T> classToBeMocked) {
this.classToBeMocked = classToBeMocked;
}
@Override
public T getObject() throws Exception {
return Mockito.mock(classToBeMocked);
}
@Override
public Class<?> getObjectType() {
return classToBeMocked;
}
@Override
public boolean isSingleton() {
return true;
}
}
接下来更新你的spring配置如下:
<beans...>
<context:component-scan base-package="com.jayway.example"/>
<bean id="someDependencyMock" class="com.jayway.springmock.MockitoFactoryBean">
<constructor-arg name="classToBeMocked" value="com.jayway.example.SomeDependency" />
</bean>
</beans>
如果您正在使用spring >= 3.0,请尝试使用spring @Configuration注释来定义应用程序上下文的一部分
@Configuration
@ImportResource("com/blah/blurk/rest-of-config.xml")
public class DaoTestConfiguration {
@Bean
public ApplicationService applicationService() {
return mock(ApplicationService.class);
}
}
如果你不想使用@ImportResource,也可以用另一种方式:
<beans>
<!-- rest of your config -->
<!-- the container recognize this as a Configuration and adds it's beans
to the container -->
<bean class="com.package.DaoTestConfiguration"/>
</beans>
有关更多信息,请参阅spring-framework-reference:基于java的容器配置