【问题标题】:How to run the same SpringBootTests for different applications如何为不同的应用程序运行相同的 SpringBootTests
【发布时间】:2018-06-22 11:48:50
【问题描述】:

我有一个 SpringBoot 多模块应用程序,类似这样:

核心 customer1 -> 取决于核心 customer2 -> 依赖于核心

我想为两者编写集成测试,但我不想复制我的核心测试代码。现在我有了一个带有 SpringBootTest(classes = Customer1Application.class) 的抽象类和很多测试类,主要是测试核心功能。

@ContextConfiguration
@SpringBootTest(classes = Customer1Application.class)
@AutoConfigureMockMvc
public abstract class AbstractSpringBootTest
{

@Autowired
protected MockMvc                               mockMvc;

@Autowired
protected Validator                             validator;

...
}

我想检查 Customer2 应用程序中的更改是否破坏了核心功能,因此我想使用 @SpringBootTest(classes = Customer2Application.class) 注释运行这些测试。

如何在注解中配置应用程序类?有没有办法在我的其他应用程序上下文中运行测试,而无需手动更改注释或复制所有步骤?

【问题讨论】:

    标签: java spring spring-boot testing


    【解决方案1】:

    我不知道它是否会起作用,但我会尝试从AbstractSpringBootTest 中删除@SpringBootTest,然后定义两个测试类,如下所示:

    @SpringBootTest(classes = Customer1Application.class)
    class Customer1ApplicationSpringBootTest extends AbstractSpringBootTest {}
    
    @SpringBootTest(classes = Customer2Application.class)
    class Customer2ApplicationSpringBootTest extends AbstractSpringBootTest {}
    

    编辑:

    所以我挖掘了 Spring Boot 的源代码并想出了this solution

    基本上为了能够使用系统属性或属性文件来配置应该测试哪个@SpringBootApplication,您需要将类org.springframework.boot.test.context.SpringBootConfigurationFinder的源复制到您自己的测试源根目录和编辑方法private Class<?> scanPackage(String source)以查看像这样的东西(你当然不必使用 Lombok):

    private Class<?> scanPackage(String source) {
        while (!source.isEmpty()) {
            val components = this.scanner.findCandidateComponents(source);
            val testConfig = System.getProperties();
            val testConfigFile = "test-config.properties";
            val applicationClassConfigKey = "main.application.class";
            try {
                testConfig.load(this.getClass().getResourceAsStream("/" + testConfigFile));
            } catch (IOException e) {
                logger.error("Error reading configuration file: {}, using default algorithm", testConfigFile);
            }
            if (testConfig.containsKey(applicationClassConfigKey)) {
                if (!components.isEmpty() && testConfig.containsKey(applicationClassConfigKey) && testConfig.getProperty(applicationClassConfigKey) != null) {
                    boolean found = false;
                    val configClassName = testConfig.getProperty(applicationClassConfigKey);
                    for (BeanDefinition component: components) {
                        if (configClassName.equals(component.getBeanClassName())) {
                            found = true;
                            break;
                        }
                    }
                    Assert.state(found,
                        () -> "Found multiple @SpringBootConfiguration annotated classes "
                            + components + ", none of which are of type " + configClassName);
                    return ClassUtils.resolveClassName(
                        configClassName, null);
                }
            } else {
                if (!components.isEmpty()) {
                    Assert.state(components.size() == 1,
                        () -> "Found multiple @SpringBootConfiguration annotated classes "
                                        + components);
                    return ClassUtils.resolveClassName(
                         components.iterator().next().getBeanClassName(), null);
                }
            }
            source = getParentPackage(source);
        }
        return null;
    }
    

    检查整个项目的link

    【讨论】:

    • 是的,它可以工作,但我需要复制所有的测试类。例如:@SpringBootTest(classes = Customer1Application.class) class CoreFunctionXYTestWithCustomer1 extends AbstractSpringBootTest {} @SpringBootTest(classes = Customer2Application.class) class CoreFunctionXYTestWithCustomer2 extends AbstractSpringBootTest {}
    • 好的,那如果你不依赖 Spring 注解,而是手动创建 ApplicationContext 进行测试呢?然后你可以事先阅读某种配置文件,并确定使用哪种配置类。
    • 是的,这样的东西会很完美,但我在谷歌上找不到任何信息如何做到这一点
    • 我编辑了我的答案,以展示如何欺骗 Spring Boot 让您通过系统属性或配置文件选择 @SpringBootApplication 类。
    【解决方案2】:

    你检查了吗? @SpringBootTest(classes = {Customer1Application.class, Customer2Application.class})

    【讨论】:

    • 如果我这样做,Spring 会尝试同时启动两个应用程序。这会导致路由映射冲突和其他一些问题。我需要一种可以清楚地将两个应用分开的方法
    • 嗯,也许这是一个解决方法,但如果您需要快速手动自定义测试,您可以:使用@Profile("testprofile") 创建测试配置类。之后只需使用 @AciveProfiles("testprofile") 运行测试以仅从此配置文件加载 bean?
    猜你喜欢
    • 1970-01-01
    • 2017-09-29
    • 2019-11-13
    • 2021-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-13
    • 1970-01-01
    相关资源
    最近更新 更多