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

San*_*Man 20 java junit spring applicationcontext

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

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

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

这个例子:

说类Foo只注入吧

public class Foo {

@Inject
Bar bar;

@Test
public void testrunSomeMethod() throws RegisterFault {
    bar.runSomeMethod();
}
Run Code Online (Sandbox Code Playgroud)

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

<beans>
     <bean id="foobar" class="some.package.FooBar"/>
     <bean id="bar" class="some.package.Bar"/>
<beans>
Run Code Online (Sandbox Code Playgroud)

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

谢谢.

Dee*_*pak 7

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

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

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


Vin*_*uri 5

是的,我们可以做到这一点,使用每个测试用例的上下文。使用测试用例所需的 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 {}
Run Code Online (Sandbox Code Playgroud)

  • 有没有基于注释的方法? (2认同)

Sar*_*eth 5

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

通常我看到三个选项。

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

  2. 为所有测试创建一次上下文。就像这里:在 junit 测试类中重用 spring 应用程序上下文这是一次测试所有测试的重大优化。

  3. 混合这两个第一点。创建一个较小的上下文仅用于测试目的。模拟一下,从未测试过但可以抛出 NPE 等的内容。就像这里:将 Mockito 模拟注入 Spring bean以增强上下文构建。并像第 2 点一样重新使用它。一次构建所有测试。我个人会选择那个。

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

  • 广告。4:你真的不能自动做到这一点。bean 在创建时可能会运行一些代码,并且无法自动确定这些代码是否重要。虽然这将是一个糟糕的编码,但您可能有一个 bean,它在创建时将一些记录添加到数据库中,然后代码的某些部分稍后读取该记录。作为开发人员,您可能能够发现此类依赖项,但您无法自动完成——这相当于停机问题或更糟。 (2认同)