如何避免SpringJUnit4ClassRunner在使用JMockit进行模拟之前初始化bean?

时间:2013-02-05 18:04:06

标签: java spring junit4 jmockit

我有一个像这样的JUnit测试类:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration( locations = { "beanDefinitions.xml"})
public class MyTest {

    @Mocked private SomeDependency usedInSpringContext;

    @Test public void letsTest() {
        ...
    }
}

问题是,Spring运行器在JMockit有机会模仿它们之前加载它的bean。怎么避免呢?这是JMockit 1.0和Spring 3.07。我宁愿让beanDefinitions.xml保持不变。

正在测试的代码是遗留的。它包含许多硬编码的spring依赖项,我无法轻易摆脱它。因此第一步 - 嘲笑。

2 个答案:

答案 0 :(得分:2)

您可以使用自定义FactoryBean。

blog中对此进行了解释。 here是示例代码。

它使用easymock或Mockito。但我相信你可以很容易地将它移植到JMockit。

编辑:我忽略了您不希望修改beanDefinitions.xml。但我的建议包括修改。

答案 1 :(得分:0)

关于Spring的一个很棒的事情,以及一般的依赖注入,就是你的类不会因代码满足它们的依赖性而变得杂乱无章。他们只是坐着等待其他人填写合作对象。所以插入模拟对象应该是微不足道的。

// no Spring runner or context configuration
public class FooTest {
    Foo foo;

    @Before
    public void setup() {
        foo = new Foo();
        foo.setDependency(mock(dependency)); // details depend on mocking framework
    }
}

使用这种方法,您不会自动装配或以其他方式注入您正在测试的对象,至少如果您打算通过将其指向模拟协作者来重新配置它,则至少不会。如果被测代码有很多依赖关系,你可以使用大量的设置代码,但这是正常的。

不可否认,有些东西(比如数据库)很难模拟,所以你需要一种不同的测试方法来验证你的SQL查询(例如)是否符合你的意思。这开始于一个单独的bean定义文件,其中包含:

<jdbc:embeded-database id="datasource"/>

有关详细信息,请参阅http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/testing.html

棘手的部分是,如果你一直没有编写Junit测试,你可能已经陷入了每个bean似乎都依赖于其他所有bean的情况。所以你试图测试的“单元”不是一个类,而是一堆相互关联的类。在这种情况下,我建议将bean定义文件分成更小的部分,然后为每个部分编写单元测试。

使用这种方法,您可以让Spring连接正在测试的代码,因为Spring配置是该单元的一部分。单元测试代码仍然模拟并插入该单元外部的依赖项。

如果您坚持完全使用真正的beanDefinitions.xml文件,那么您正在编写集成测试,而不是单元测试。