更好的性能来整合 Spring 配置 类?

Better performance to consolidate Spring configuration classes?

我有一个基本的测试设置,其中 TestA 依赖于 ConfigATestB 依赖于 ConfigB


@Configuration
public class ConfigA {

    // define A beans

}

@Configuration
public class ConfigB {

    // define B beans

}

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { ConfigA.class })
public class TestA {

    @Test
    public void testA() {
        // test with A beans
    }

}

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { ConfigB.class })
public class TestB {

    @Test
    public void testB() {
        // test with B beans
    }

}

我想 运行 TestATestB 使用测试套件 AllTests

@RunWith(Suite.class)
@SuiteClasses({ TestA.class, TestB.class })
public class AllTests {

}

就目前而言,运行宁 AllTests 将强制 Spring 在 运行 时加载 ConfigAConfigB

ConfigAConfigB 合并到 ConfigC 并让两个测试都使用 ConfigC 来代替性能会更好吗?

@Configuration
public class ConfigC {

    // define A and B beans

}

它应该或多或少是相同的,性能方面 - Spring 测试以任何一种方式缓存上下文,因此如果您的任何其他测试使用 ContextA 或 ContextB,它们将从缓存中重用而不是重新创建对于每个测试。与合并的上下文相比,使用两个单独的上下文(A 和 B)会产生更多的开销,但应该不会那么明显。

引用自the official documentation

The Spring TestContext Framework provides consistent loading of Spring ApplicationContexts and WebApplicationContexts as well as caching of those contexts. Support for the caching of loaded contexts is important, because startup time can become an issue — not because of the overhead of Spring itself, but because the objects instantiated by the Spring container take time to instantiate. For example, a project with 50 to 100 Hibernate mapping files might take 10 to 20 seconds to load the mapping files, and incurring that cost before running every test in every test fixture leads to slower overall test runs that reduce developer productivity.

By default, once loaded, the configured ApplicationContext is reused for each test. Thus the setup cost is incurred only once per test suite, and subsequent test execution is much faster. In this context, the term test suite means all tests run in the same JVM — for example, all tests run from an Ant, Maven, or Gradle build for a given project or module.

以下是 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.

Since Spring Framework 4.3, the size of the context cache is bounded with a default maximum size of 32. Whenever the maximum size is reached, a least recently used (LRU) eviction policy is used to evict and close stale contexts. The maximum size can be configured from the command line or a build script by setting a JVM system property named spring.test.context.cache.maxSize. As an alternative, the same property can be set programmatically via the SpringProperties API.