自动装配的 Spring 集成测试很慢
我正在尝试加快我们环境中的集成测试速度。我们所有的类都是自动装配的。在我们的 applicationContext.xml 文件中,我们定义了以下内容:
<context:annotation-config/>
<context:component-scan base-package="com.mycompany.framework"/>
<context:component-scan base-package="com.mycompany.service"/>
...additional directories
我注意到 Spring 正在扫描上面指出的所有目录,然后迭代每个 bean 并缓存每个 bean 的属性。 (我查看了来自 spring 的 DEBUG 消息)
因此,以下测试大约需要 14 秒才能运行:
public class MyTest extends BaseSpringTest {
@Test
def void myTest(){
println "test"
}
}
有没有办法延迟加载配置?我尝试添加 default-lazy-init="true"
但这不起作用。
理想情况下,仅实例化测试所需的 Bean。
提前致谢。
更新:我应该在之前声明这一点,我不想为每个测试都有一个上下文文件。我也不认为仅用于测试的一个上下文文件会起作用。 (这个测试上下文文件最终将包括所有内容)
I am trying to speed up the Integration tests in our environment. All our classes are autowired. In our applicationContext.xml file we have defined the following:
<context:annotation-config/>
<context:component-scan base-package="com.mycompany.framework"/>
<context:component-scan base-package="com.mycompany.service"/>
...additional directories
I have noticed that Spring is scanning all directories indicated above and then iterates over each bean and caches the properties of each one. (I went over the DEBUG messages from spring)
As a result, the following test takes about 14 seconds to run:
public class MyTest extends BaseSpringTest {
@Test
def void myTest(){
println "test"
}
}
Is there any way to lazy load the configuration? I tried adding default-lazy-init="true"
but that didn't work.
Ideally, only the beans required for the test are instantiated.
thanks in advance.
Update: I should have stated this before, I do not want to have a context file for each test. I also do not think one context file for just the tests would work. (This test context file would end up including everything)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
如果您确实想加快应用程序上下文的速度,请禁用组件扫描并在运行任何测试之前执行以下例程
除此之外,启用>
由于您需要在运行任何测试之前执行上述例程,您可以创建一个抽象类,您可以在其中运行以下内容
为测试环境设置 Java 系统属性,如下所示
现在
,对于每个测试类,只需扩展初始化程序
If you really want to speed up your application context, disable your <component-scan and performs the following routine before running any test
Besides that, enable <context:annotation-config/>
As you need to perform the routine above before running any test, you can create an abstract class where you can run the following
Set up a Java system property for testing environment as follows
And
Now, for each test class, just extends Initializer
一种方法是完全跳过自动检测,并加载单独的上下文(带有测试所需的组件)或在运行时重新定义 bean(在测试运行之前)。
此线程讨论 bean 的重新定义以及用于执行此操作的自定义测试类:
Spring beans redefinition在单元测试环境中
One approach is to skip the auto detection completely and either load up a separate context (with the components required for the test) or redefine your beans at runtime (prior to the test running).
This thread discusses redefinition of beans and a custom test class for doing this:
Spring beans redefinition in unit test environment
这是自动检测组件所付出的代价——速度较慢。尽管您的测试只需要某些 bean,但您的
范围更广,Spring 将实例化并初始化它找到的每个 bean。我建议您为测试使用不同的 beans 文件,该文件仅定义测试本身所需的 beans,即不使用
。This is the price you pay for auto-detection of components - it's slower. Even though your test only requires certain beans, your
<context:component-scan>
is much broader, and Spring will instantiate and initialise every bean it finds.I suggest that you use a different beans file for your tests, one which only defines the beans necessary for the test itself, i.e. not using
<context:component-scan>
.也许您需要的是重构您的配置以使用更少的自动装配。我的方法几乎总是按名称连接 bean,试图使设计明确,但同时也不要太冗长,当明确您正在使用它来隐藏次要细节时使用自动连接。
附录:
如果这还不够,并且您正在使用 junit,您可能需要使用 JUnit Addons 项目。 DirectorySuiteBuilder 类从目录结构动态构建测试套件。所以你可以在这段代码之前做一些类似
初始化Spring上下文的事情,你可以一次运行所有测试。但是,如果每个测试都假设一个“干净”的 Spring 上下文,那么您可能会迷失方向。
Probably what you need is to refactor your config to use less autowiring. My approach is almost always wire the beans by name, trying to be explicit with the design but, at the same time, not being too verbose either, using autowiring when is clear that you are using it in order to hide minor details.
Addendum:
If that is not enough and you are using junit, you may want to use a utility from the JUnit Addons project. The class
DirectorySuiteBuilder
dynamically builds up a test suite from a directory structure. So you can make something likeInitializing the Spring context before this code, you can run all tests at once. However, if each test assume a "clean" Spring context, then you are probably lost.
在这种情况下,你需要找到一个平衡点。
一方面,您理所当然地希望在尽可能短的时间内运行测试以快速获得结果。当在持续集成工作的团队环境中工作时,这一点尤其重要。
另一方面,您也可能希望测试的配置尽可能简单,这样测试套件的维护就不会变得太麻烦而无用。
但最终,您需要找到自己的平衡并做出决定。
我建议创建一些用于测试的上下文配置文件来对一些测试进行分组,这样这样一个简单的测试就不会花费很长时间,只需由 Spring 配置即可,同时将配置文件的数量保持在您可以管理的最低限度。
In this kind of situation, you will need to find a balance.
On one hand, you would rightly want to run the tests in a shortest possible time to get the results quick. This is especially important when working in a team environment with continuous integration working.
On the other hand, you would also rightly want to keep the configuration of tests as simple as possible so the maintenance of test suite would not become too cumbersome to be useful.
But at the end of the day, you will need to find your own balance and make a decision.
I would recommend creating a few context configuration files for testing to group some tests so such a simple test would not take long time simply being configured by Spring, while keeping the number of configuration files to minimum you can manage.
约定bean工厂旨在解决这个问题,并显着加快整个过程,3倍或3倍更多的。
Convention bean factory is designed to solve this problem and speeds up the whole process significantly, 3x or more.
由于这里的答案都没有为我解决这个问题,所以我添加自己的经验。
我的问题是 Spring、Hibernate 和 EhCache 联合起来,试图用冗长的 DEBUG 消息淹没我的控制台,导致日志不可读,而且更糟糕的是,性能低得难以忍受。
配置他们的日志级别修复了所有问题:
Since none of the answers here solved this problem for me, I add my own experience.
My problem was that Spring, Hibernate and EhCache grouped up in the attempt of drowning my console with verbose
DEBUG
messages, resulting unreadable log and - far worse - unbearable low performance.Configuring their log levels fixed all up: