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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/39014551/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 04:00:59  来源:igfitidea点击:

How to tell spring to only load the needed beans for the JUnit test?

javaspringjunitapplicationcontext

提问by SandMan

A simple question that might have an advanced answer.

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

The Question: My question is, is there a way to instantiate only the classes, in your application context, needed for that specific JUnit test ?

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

The Reason: My application context is getting quite big. I also do a lot of integration tests so you I guess you would understand when I say that every time I run a test all the classes in my application context get instantiated and this takes time.

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

The Example:

这个例子:

Say class Foo inject only bar

说 Foo 类只注入吧

public class Foo {

@Inject
Bar bar;

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

but the application context has beans foobar and bar. I know this is not a vaild application context but rest assure all my code works.

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

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

So how do I tell spring to only instantiate Bar and ignore FooBar for the test class foo.

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

Thank you.

谢谢你。

采纳答案by Sarseth

It's not direct answer, so I'd would not mark as solution. But hope it's helpful.

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

Generally I see three options.

通常我看到三个选项。

  1. As VinayVeluri answered nicely. Create separate contexts and launch them in every tests separately.

  2. Create context one time per all tests. Just like here: Reuse spring application context across junit test classesIt's a big optimization for testing all tests at once.

  3. Mix those two first points. Create one smaller context only for testing purpose. Mock that, what's never is tested but can throw NPE etc. Like here: Injecting Mockito mocks into a Spring beanto boost up context build. And re-use it like in point 2. One time build for all tests. Personally I'd go with that one.

  4. This one waiting for answer about some kind of smart test runner, which creates minimum needed context per test.

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

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

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

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

回答by Deepak

Consider adding default-lazy-init="true"to your spring context xml beans tag (or add lazy-init="true"to those specific beans that take a long time starting up). This will ensure that only those beans are created that called with applicationContext.getBean(class-or-bean-name) or injected via @Autowired/ @Injectinto your tests. (Some other types of beans like @Scheduledbeans will be created nevertheless but you need to check if that's a problem or not)

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

(if you use spring Java configuration, add @Lazyto the config files)

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

Caveat- If there is a bean that is not initialized explicitly with applicationContext.getBean() or injected as a dependency used by the bean obtained by using applicationContext.getBean(), then that bean will NO LONGER be constructed or initialized. Depending upon your application, that can cause things to fail OR not. Maybe you can selectively mark those beans as lazy-init="false"

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

回答by VinayVeluri

Yes, we can do that, using context per test case. Prepare a test context xml file with the beans required for your test case.

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

If you use maven, place the test-context.xml under src/test/resourcesfolder.

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

Annotate your required test class with the following annotation

使用以下注释注释您所需的测试类

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

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

This helps in loading only specific beans for the test case.

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

If you have two kinds of test cases, then

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

@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 {}