在多个 Gradle 项目中重复使用 spring 测试上下文
Reusing a spring test context across multiple Gradle projects
我正在进行典型的 Gradle 多项目构建:
project(':common') {
}
project(':project-a') {
dependencies {
compile project(':common')
..
}
}
...
project(':project-n') {
dependencies {
compile project(':common')
..
}
}
project(':app') {
dependencies {
compile project(':project-a')
..
compile project(':project-n')
..
}
}
所有名为 integrataionTest
的子项目都有一个共同任务,即 运行 所有集成测试套件 (classes)。这些 classes 继承自一个共同的父级,用典型的 spring 测试内容注释:
@ContextConfiguration // needed until Spock supports @SpringBootTest
@SpringBootTest(classes = IntegrationTestConfiguration)
@ActiveProfiles("test")
class BaseTest extends Specification {
IntegrationTestConfiguration
是用 @EnableAutoConfiguration
注释的 @Configuration
class 并且只预定义了一些除了实际成熟的 @SpringBootApplication
class.
问题是调用gradle integrationTest
似乎开始组件扫描,设置Spring上下文,运行每个子项目中的测试然后丢弃上下文,当所有这些都基本相同时。
:app:integrationTest
[..] INFO 38320 --- [ Thread-5] o.s.w.c.s.GenericWebApplicationContext : Closing org.springframework.web.context.support.GenericWebApplicationContext@206e239d: startup date [..]; root of context hierarchy
:common:integrationTest
[..] INFO 38361 --- [ Thread-5] o.s.w.c.s.GenericWebApplicationContext : Closing org.springframework.web.context.support.GenericWebApplicationContext@a6d8c9f: startup date [..]; root of context hierarchy
:project-a:integrationTest
[..] INFO 38362 --- [ Thread-5] o.s.w.c.s.GenericWebApplicationContext : Closing org.springframework.web.context.support.GenericWebApplicationContext@181313ca: startup date [..]; root of context hierarchy
..
:project-n:integrationTest
[..] INFO 38363 --- [ Thread-5] o.s.w.c.s.GenericWebApplicationContext : Closing org.springframework.web.context.support.GenericWebApplicationContext@68ab1a32: startup date [..]; root of context hierarchy
我想知道是否有办法让整个设置 运行 只需一次,然后在所有不同的子项目中重复使用。
我不认为它应该按照您希望的方式工作 - 您的每个子项目都有自己的测试任务,并且其测试需要与其他项目隔离执行。
此外,引用Gradle's official documentation:
Test are always run in (one or more) separate JVMs. The sample below shows various configuration options.
这意味着因为您的测试任务不会共享 JVM,所以它们实际上不能共享 Spring 上下文实例。原因是 Spring 缓存测试上下文的方式。这是来自 the official documentation 的引述:
The Spring TestContext framework stores application contexts in a static cache. This means that the context is literally stored in a static variable. In other words, if tests execute in separate processes the static cache will be cleared between each test execution, and this will effectively disable the caching mechanism.
To benefit from the caching mechanism, all tests must run within the same process or test suite. This can be achieved by executing all tests as a group within an IDE. Similarly, when executing tests with a build framework such as Ant, Maven, or Gradle it is important to make sure that the build framework does not fork between tests. For example, if the forkMode for the Maven Surefire plug-in is set to always or pertest, the TestContext framework will not be able to cache application contexts between test classes and the build process will run significantly slower as a result.
也就是说,如果您的子项目的 Spring 配置确实没有差异,您可以创建一个新的子项目,仅用于集成测试目的,然后在那里执行所有集成测试,尽管如果您的子项目在 Spring 配置上没有差异,您也许可以合并它们或至少以不同的方式组织它们。
我正在进行典型的 Gradle 多项目构建:
project(':common') {
}
project(':project-a') {
dependencies {
compile project(':common')
..
}
}
...
project(':project-n') {
dependencies {
compile project(':common')
..
}
}
project(':app') {
dependencies {
compile project(':project-a')
..
compile project(':project-n')
..
}
}
所有名为 integrataionTest
的子项目都有一个共同任务,即 运行 所有集成测试套件 (classes)。这些 classes 继承自一个共同的父级,用典型的 spring 测试内容注释:
@ContextConfiguration // needed until Spock supports @SpringBootTest
@SpringBootTest(classes = IntegrationTestConfiguration)
@ActiveProfiles("test")
class BaseTest extends Specification {
IntegrationTestConfiguration
是用 @EnableAutoConfiguration
注释的 @Configuration
class 并且只预定义了一些除了实际成熟的 @SpringBootApplication
class.
问题是调用gradle integrationTest
似乎开始组件扫描,设置Spring上下文,运行每个子项目中的测试然后丢弃上下文,当所有这些都基本相同时。
:app:integrationTest
[..] INFO 38320 --- [ Thread-5] o.s.w.c.s.GenericWebApplicationContext : Closing org.springframework.web.context.support.GenericWebApplicationContext@206e239d: startup date [..]; root of context hierarchy
:common:integrationTest
[..] INFO 38361 --- [ Thread-5] o.s.w.c.s.GenericWebApplicationContext : Closing org.springframework.web.context.support.GenericWebApplicationContext@a6d8c9f: startup date [..]; root of context hierarchy
:project-a:integrationTest
[..] INFO 38362 --- [ Thread-5] o.s.w.c.s.GenericWebApplicationContext : Closing org.springframework.web.context.support.GenericWebApplicationContext@181313ca: startup date [..]; root of context hierarchy
..
:project-n:integrationTest
[..] INFO 38363 --- [ Thread-5] o.s.w.c.s.GenericWebApplicationContext : Closing org.springframework.web.context.support.GenericWebApplicationContext@68ab1a32: startup date [..]; root of context hierarchy
我想知道是否有办法让整个设置 运行 只需一次,然后在所有不同的子项目中重复使用。
我不认为它应该按照您希望的方式工作 - 您的每个子项目都有自己的测试任务,并且其测试需要与其他项目隔离执行。
此外,引用Gradle's official documentation:
Test are always run in (one or more) separate JVMs. The sample below shows various configuration options.
这意味着因为您的测试任务不会共享 JVM,所以它们实际上不能共享 Spring 上下文实例。原因是 Spring 缓存测试上下文的方式。这是来自 the official documentation 的引述:
The Spring TestContext framework stores application contexts in a static cache. This means that the context is literally stored in a static variable. In other words, if tests execute in separate processes the static cache will be cleared between each test execution, and this will effectively disable the caching mechanism.
To benefit from the caching mechanism, all tests must run within the same process or test suite. This can be achieved by executing all tests as a group within an IDE. Similarly, when executing tests with a build framework such as Ant, Maven, or Gradle it is important to make sure that the build framework does not fork between tests. For example, if the forkMode for the Maven Surefire plug-in is set to always or pertest, the TestContext framework will not be able to cache application contexts between test classes and the build process will run significantly slower as a result.
也就是说,如果您的子项目的 Spring 配置确实没有差异,您可以创建一个新的子项目,仅用于集成测试目的,然后在那里执行所有集成测试,尽管如果您的子项目在 Spring 配置上没有差异,您也许可以合并它们或至少以不同的方式组织它们。