如何在多Gradle项目中的JUnit Spring上下文中加载资源属性?

Dim*_*iwa 7 java spring spring-mvc gradle spring-boot

我有以下项目树:

??? app
?   ??? build.gradle
?   ??? src
?       ??? main
?       ?   ??? java
?       ?   ?   ??? child
?       ?   ?       ??? app
?       ?   ?           ??? Application.java
?       ?   ??? resources
?       ?       ??? application-default.yaml
?       ??? test
?           ??? java
?               ??? child
?                   ??? app
?                       ??? ApplicationTest.java
??? build.gradle
??? childA
?   ??? build.gradle
?   ??? src
?       ??? main
?           ??? java
?               ??? child
?                   ??? a
?                       ??? BaseGreeterImpl.java
?                       ??? ChildAConfig.java
?                       ??? Greeter.java
?                       ??? MySpringProperties.java
??? childB
?   ??? build.gradle
?   ??? src
?       ??? main
?           ??? resources
?               ??? application-test.yaml
?               ??? childB.properties
??? childC
?   ??? build.gradle
?   ??? src
?       ??? main
?       ?   ??? java
?       ?   ?   ??? child
?       ?   ?       ??? c
?       ?   ?           ??? ChildCConfig.java
?       ?   ?           ??? PropertyGreeterImpl.java
?       ?   ??? resources
?       ?       ??? childc.properties
?       ??? test
?           ??? java
?               ??? child
?                   ??? c
?                       ??? TestYamlImport.java
?                       ??? TestGreeter.java
??? settings.gradle
Run Code Online (Sandbox Code Playgroud)

我有以下测试类:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { ChildCConfig.class }, loader = AnnotationConfigContextLoader.class)
@ActiveProfiles("test")
@SpringBootTest
public class TestYamlImport {

    @Autowired
    private MySpringProperties properties;

    @Test
    public void readChildAYaml() {
        assertThat(properties.getName()).isEqualTo("it-is-another-thing");
    }

}
Run Code Online (Sandbox Code Playgroud)

预期

我希望properties.getName()childB/src/main/resources/application-test.yaml中的资源childB中读取值.

结果

我明白了 null

再生产

GitHub:https://github.com/kopax/adk/tree/adk-spring

一个班轮:

git clone git@github.com:kopax/adk.git && cd adk && git checkout adk-spring && ./gradlew build --info
Run Code Online (Sandbox Code Playgroud)

在再现项目中有一个名为childC/src/test/java/childC/TestGreeter.java的测试childB.properties,通过导入证明它不是类路径问题.

所以这是我的问题:

  • 在使用时,弹簧是否以某种方式限制了类路径分辨率@ConfigurationProperties

  • 我还没有找到一种方法来读我的application-test.yml配置中的@Bean初始化在childA测试范围childB,这怎么可能?

Szy*_*iak 3

您使用AnnotationConfigContextLoader而不是 (默认)有什么特殊原因吗SpringBootContextLoader?您面临的问题不是由类路径中的文件丢失引起的(您可以复制application-test.yaml到任何文件src/main/resources或具有相同的结果),而是不使用负责通过从众所周知的文件位置加载属性来配置上下文的src/test/resources事实(例如你的情况)。AnnotationConfigContextLoaderConfigFileApplicationListenerapplication-{profile}.yaml

您可以轻松比较使用每个加载器时加载的属性。首先,您可以检查一下AnnotationConfigContextLoader做了什么 - 只需在 AbstractGenericContextLoader.java 文件的第 128 行放置一个断点,然后在您最喜欢的 IDE 中运行调试器:

在此输入图像描述

接下来您可以研究变量context-> environment-> propertySources-> propertySourceList。您会发现 5 个房产来源:

在此输入图像描述

它们都不会从配置文件(例如application.yml或 )加载属性application.properties

现在让我们在SpringBootContextLoader课堂上做同样的事情。首先删除

loader = AnnotationConfigContextLoader.class
Run Code Online (Sandbox Code Playgroud)

MyEntityTest在 SpringApplication.java 文件的第 303 行放置一个断点:

在此输入图像描述

我们就在应用程序上下文刷新之前。现在让我们研究变量context-> environment-> propertySources-> propertySourceList

在此输入图像描述

我们可以看到的第一个区别是,现在我们有 7 个属性源,而不是上一个示例中的 5 个。最重要的是——ConfigFileApplicationListener.ConfigurationPropertySources就在这里。此类使应用程序上下文知道application-{profile}.yaml属性文件的存在。

在此输入图像描述

正如您所看到的,这只是使用正确的上下文加载器的问题。代替

@ContextConfiguration(classes = { ChildCConfig.class }, loader = AnnotationConfigContextLoader.class)
Run Code Online (Sandbox Code Playgroud)

@ContextConfiguration(classes = { ChildCConfig.class }, loader = SpringBootContextLoader.class)
Run Code Online (Sandbox Code Playgroud)

或者

@ContextConfiguration(classes = { ChildCConfig.class })
Run Code Online (Sandbox Code Playgroud)

因为这个加载器是使用注释时的默认加载器@SpringBootTest,您将使您的测试顺利通过。我希望它有帮助。