假设我将XML Spring配置的这两部分放在两个不同的文件中;
//daoContext.xml
<bean id="myDao" class="com.MyDao"/>
//logicContext.xml
<bean id="myLogic" class="com.MyLogic">
<constructor-arg ref="myDao"/><!--or other type of injection--?
</bean>
还有测试类:
@ContextConfiguration("logicContext.xml")
public class BaseLogicTest extends AbstractTestNGSpringContextTests {
@Autowired
private MyLogic myLogic;
@Test
public void testMyTestable() {
//...
}
}
现在,我想要的是能够模拟MyDao
类并注入MyLogic
以BaseLogicTest
注入MyLogic
所以我可以使用MyDao
嘲笑{{1}}。这是否可以使用弹簧/弹簧测试?
答案 0 :(得分:2)
最简单的解决方案是加载所有xml。并在测试用例中手动替换依赖。
@ContextConfiguration("logicContext.xml")
public class BaseLogicTest extends AbstractTestNGSpringContextTests {
@Autowired
private MyLogic myLogic;
@Before
public void injectTestDoubles() {
myLogic.setMyDao(...);
}
@DirtiesContext
@Test ...//test methods
}
但是这会破坏应用程序上下文,所以如果在其他测试用例中需要“真正的”myDao共享相同的应用程序上下文,则需要@DirtiesContext。
最受欢迎的解决方案(我的个人意见:P)是使用mockito和特定于测试的xml。
//daoContext.xml
<bean id="myDao" class="com.MyDao"/>
//logicContext.xml
<bean id="myLogic" class="com.MyLogic">
<constructor-arg ref="myDao"/><!--or other type of injection--?
</bean>
//test-logicContext.xml
<bean id="myDao" class="org.mockito.Mockito" factory-method="mock">
<constructor-arg value="com.MyDao" />
</bean>
@ContextConfiguration({"logicContext.xml", "test-logicContext.xml"})
public class BaseLogicTest extends AbstractTestNGSpringContextTests {
@Autowired
private MyLogic myLogic;
@Autowired
private MyDao myDao;//retrieve mock so you could define expectations
@Test //test methods
@After public void clearMocks() {
Mockito.reset(myDao);//this is important if you have several test methods
}
}
此解决方案适用于其他模拟框架,如easyMock。
答案 1 :(得分:1)
您可以通过创建FactoryBean
来创建MyDao
(或任何)模拟注入您的MyLogic
实例。
public class FactoryBeanForMocks<T> implements FactoryBean<T> {
private Class<T> mockClass;
public FactoryBeanForMocks(Class<T> mockClass) {
super();
this.mockClass = mockClass;
}
@Override
public T getObject() throws Exception {
return Mockito.mock(mockClass);
}
@Override
public Class<?> getObjectType() {
return mockClass;
}
@Override
public boolean isSingleton() {
return true;
}
}
将工厂bean条目放入logicContext.xml
,以便可以将MyDao
的模拟注入MyLogic
:
//logicContext.xml
<bean id="myLogic" class="com.MyLogic">
<constructor-arg ref="myDao"/><!--or other type of injection--?
</bean>
<bean id="myDao" class="x.y.z.FactoryBeanForMocks">
<constructor-arg name="mockClass" value="x.y.MyDao"></constructor-arg>
</bean>
这是你的测试类:
@ContextConfiguration("logicContext.xml")
public class BaseLogicTest extends AbstractTestNGSpringContextTests {
@Autowired
private MyLogic myLogic;
//You can inject the mock myDao into it so that you can stub/verify method calls on it
@Autowired
private MyDao myDao;
@Test
public void testMyTestable() {
//...
when(myDao.process()).thenReturn("a");//stubbing myDao.process()
assertEquals("a", myLogic.processRequest());// assuming myLogic.processRequest() calls myDao.process()
}
}