如何告诉spring只加载JUnit测试所需的bean?

时间:2016-08-18 09:26:43

标签: java spring junit applicationcontext

一个可能有高级答案的简单问题。

问题: 我的问题是,有没有办法在应用程序上下文中仅实例化特定JUnit测试所需的类?

原因: 我的应用程序环境变得非常大。我也做了很多集成测试,所以你猜我会理解当我说每次运行测试时,我的应用程序上下文中的所有类都会被实例化,这需要时间。

示例:

假设类Foo只注入了条

public class Foo {

@Inject
Bar bar;

@Test
public void testrunSomeMethod() throws RegisterFault {
    bar.runSomeMethod();
}

但是应用程序上下文有bean foobar和bar。我知道这不是一个虚拟应用程序上下文,但请确保我的所有代码都能正常工作。

<beans>
     <bean id="foobar" class="some.package.FooBar"/>
     <bean id="bar" class="some.package.Bar"/>
<beans>

那么我怎么告诉spring只实例化Bar并忽略测试类foo的FooBar。

谢谢。

3 个答案:

答案 0 :(得分:7)

考虑将default-lazy-init="true"添加到spring context xml beans标记(或将lazy-init="true"添加到需要很长时间启动的特定bean中)。 这将确保只创建那些使用applicationContext.getBean(class-or-bean-name)调用或通过@Autowired / @Inject注入到测试中的bean。 (不过会创建一些其他类型的bean,比如@Scheduled bean,但你需要检查这是否是一个问题)

(如果使用spring Java配置,请将@Lazy添加到配置文件中)

警告 - 如果有一个bean没有使用applicationContext.getBean()显式初始化或者作为使用applicationContext.getBean()获得的bean使用的依赖项注入,那么该bean将不再构建或初始化。根据您的应用程序,这可能导致事情失败或不。也许您可以选择性地将这些bean标记为lazy-init="false"

答案 1 :(得分:3)

是的,我们可以使用每个测试用例的上下文来做到这一点。使用测试用例所需的bean准备测试上下文xml文件。

如果您使用maven,请将test-context.xml放在src/test/resources文件夹下。

使用以下注释

注释所需的测试类

@ContextConfiguration(locations = "classpath:test-application-context.xml")

这有助于仅加载测试用例的特定bean。

如果您有两种测试用例,那么

@Runwith(SpringJUnit4Runner.class)
@ContextConfiguration(locations = "classpath:test-context-case1.xml")
public class TestClassCase1 {}

@Runwith(SpringJUnit4Runner.class)
@ContextConfiguration(locations = "classpath:test-context-case2.xml")
public class TestClassCase2 {}

答案 2 :(得分:3)

这不是直接答案,所以我不会将其标记为解决方案。但希望它有用。

一般来说,我看到三种选择。

  1. 正如VinayVeluri回答得很好。创建单独的上下文并分别在每个测试中启动它们。

  2. 每次测试都会创建一次上下文。就像这里:Reuse spring application context across junit test classes这是一次性测试所有测试的重大优化。

  3. 混合这两个第一点。仅为测试目的创建一个较小的上下文。嘲笑,什么从未经过测试,但可以抛出NPE等。像这里:Injecting Mockito mocks into a Spring bean来提升上下文构建。并在第2点重新使用它。一次性构建所有测试。就个人而言,我会选择那个。

  4. 这个等待关于某种智能测试运行器的答案,它为每次测试创建了最少的必需上下文。