I have the following project tree:
├── 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
I have the following test class :
@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");
    }
}
I expect properties.getName() to read the value from resource childB in childB/src/main/resources/application-test.yaml.
I get null
GitHub: https://github.com/kopax/adk/tree/adk-spring
One liner:
git clone [email protected]:kopax/adk.git && cd adk && git checkout adk-spring && ./gradlew build --info
There is a test called childC/src/test/java/childC/TestGreeter.java in the reproduction project which prove with childB.properties import that it is not a classpath issue.
So here are my questions :
Is spring limiting the classpath resolution somehow when using @ConfigurationProperties ?
I haven't found a way to read my application-test.ymlwithin a configuration @Bean initialized in childA from the test scope of childB, how is this possible ?
Is there any particular reason you are using AnnotationConfigContextLoader instead of (default) SpringBootContextLoader? The problem you are facing is not caused by file missing in the classpath (you can copy application-test.yaml to any src/main/resources or src/test/resources with the same result) but the fact that AnnotationConfigContextLoader does not use ConfigFileApplicationListener that is responsible for configuring context by loading properties from well known file locations (like application-{profile}.yaml in your case).
You can easily compare what properties are loaded when using each loader. Firstly you can check what AnnotationConfigContextLoader does - just put a breakpoint at line 128 of AbstractGenericContextLoader.java file and run debugger in your favorite IDE:

Next you can investigate variable context -> environment -> propertySources -> propertySourceList. You will find 5 property sources:

None of them loads properties from config files like application.yml or application.properties.
Now let's do the same but with SpringBootContextLoader class. Firstly remove 
loader = AnnotationConfigContextLoader.class
in MyEntityTest and put a breakpoint at line 303 in SpringApplication.java file:

Here we are right before application context gets refreshed. Now let's investigate variable context -> environment -> propertySources -> propertySourceList:

The first difference we can see is that now we have 7 property sources instead of 5 as it was in the previous example. And what is most important - ConfigFileApplicationListener.ConfigurationPropertySources is here. This class makes application context aware of application-{profile}.yaml properties file existence.

So as you can see it is only a matter of using correct context loader. Replace
@ContextConfiguration(classes = { ChildCConfig.class }, loader = AnnotationConfigContextLoader.class)
with
@ContextConfiguration(classes = { ChildCConfig.class }, loader = SpringBootContextLoader.class)
or
@ContextConfiguration(classes = { ChildCConfig.class })
as this loader is a default one when using @SpringBootTest annotation and you will make your test passing like a charm. I hope it helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With