1

假设我将 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这样我就可以使用模拟MyLogicMyDao. 这可能使用 Spring/Spring 测试吗?

4

2 回答 2

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。

于 2013-09-11T01:36:11.890 回答
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()
    }
}
于 2013-09-09T11:49:53.920 回答