Spring配置模拟给出两个不同的实例

时间:2014-02-07 12:01:03

标签: java spring testing easymock

注意:我故意从类和对象的名称中删除了单词,所以请原谅我的代码示例中的可怕名称

我有一个测试类,它使用一些测试Spring上下文文件来设置我的应用程序。该应用程序是Web服务的包装器。

由于这是一个测试,我已经模拟了有问题的Web服务的主界面(ITransporter类)。这使我能够设置期望,以便我可以检查发送到Web服务的请求是否:以预期的格式;有预期的字段完成;等...

我的模拟在名为test-beans-context.xml的文件中定义,并传递到一些服务bean,如下所示:

<bean id="mockTransporter" class="org.easymock.EasyMock" factory-method="createMock" scope="singleton">
    <constructor-arg index="0" value="transport.ITransporter" />
</bean>
<bean id="accountService" class="service.AccountService">
    <property name="transporter" ref="mockTransporter" />
</bean>

此上下文文件用于2个地方。 (我担心这是我的问题所在。)

第一个是测试类,定义如下:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration( locations={"classpath:test-beans-context.xml"} )
public class AbstractIntegrationTest {

    @Autowired
    private ITransporter mockTransporter;

    //Some tests that perform expectations like the following:
    //  EasyMock.reset( this.mockTransporter );
    //  EasyMock.expect( this.mockTransporter.sendRequest( EasyMock.capture(this.requestXmlCapture) ) ).andReturn( responseXml );
}

第二个位置是在用于发送请求的逻辑路径中的类中。它加载一个单独的XML上下文文件/lite-api-context.xml,然后在我的测试设置中导入测试文件。

public class Factory implements IFactory {
    public Factory() {
        context = new ClassPathXmlApplicationContext("/lite-api-context.xml");
    }
    @Override
    public IAccountService getAccountService() {
        return (IAccountService) context.getBean("accountService");
    }
}

lite-api-context.xml包括:

<import resource="classpath:/test-beans-context.xml" />

我的问题是,在测试类中,我得到了一个不同的模拟ITransporter实例,最终被我的其他服务使用。因此,我设置的期望从未实际执行,因为模拟最终会成为不同的实例。

有没有办法确保我在两个地方都获得相同的实例?

或者我是否必须创建自己的ITransporter接口的单例测试实现? (基本上创建一个与我的模拟行为完全相同的存根。)

编辑:(答案)

正如Thom所说,似乎我需要创建自己的类来管理模拟。

我想在这里添加我的解决方案,以防任何人遇到类似的问题。

刚刚写了一个像这样的快速静态类:

public class MockTransporter {

    private static ITransporter mockTransporter = EasyMock.createMock(ITransporter.class);

    public static final ITransporter getInstance() {
        return mockTransporter;
    }
}

并且必须将XML配置更改为:

<bean id="mockTransporter" class="MockTransporter" factory-method="getInstance" />

2 个答案:

答案 0 :(得分:1)

是的,这是一个问题。当您创建一个新的上下文时,就像为Spring创建一个新的对象空间一样。在XML文件中创建的文件与在手工上下文中创建的文件不同。它们总会产生不同的变量。

我之前已被烧过。

你只希望如果你想要同样的人来管理自己的单身人士。

答案 1 :(得分:1)

解决此问题的理想方法是将Factory创建为Spring bean,并将AccountService注入Factory bean。 通常,在生产代码中应避免使用context.getBean(),因为它会损害控制反转的概念(有关更多信息,请参阅:Why is Spring's ApplicationContext.getBean considered bad?)。可以在测试代码中使用它。