Stefan Widerin opened SPR-14068 and commented
I think the described behavior for @TestPropertySource in the Javadoc doesn't match the actual behavior. I was expecting in this snippet...
@TestPropertySource(
locations = "classpath:test.properties",
properties = "key=certainValue"
)
... that certainValue would be used over every previously defined value for key, also overwriting a definition in test.properties, as the Javadoc says that inlined properties get highest precedence. But I never saw certainValue being used, for whatever reason.
Affects: 4.2.4
Referenced from: commits https://github.com/spring-projects/spring-framework/commit/43661ededbc1ad0070fe67ecab7a2a239822f19c
Comment From: spring-projects-issues
Sam Brannen commented
This feature works as advertised in the Javadoc.
Specifically, given explicit.properties which contains the following:
explicit = enigma
... the following test passes as expected.
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@TestPropertySource(locations = "explicit.properties", properties = "explicit = inlined")
public class InlinedPropertiesOverridePropertiesFilesTestPropertySourceTests {
@Autowired Environment env;
@Value("${explicit}") String explicit;
@Test
public void inlinedPropertyOverridesValueFromPropertiesFile() {
assertEquals("inlined", env.getProperty("explicit"));
assertEquals("inlined", this.explicit);
}
@Configuration
static class Config {
@Bean
public static PropertySourcesPlaceholderConfigurer placeholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
}
This test is now part of the Spring test suite, as can be seen in the following commit: https://github.com/spring-projects/spring-framework/commit/43661ededbc1ad0070fe67ecab7a2a239822f19c
I am therefore resolving this issue as Works as Designed.
However, if you can provide a test case that proves otherwise, feel free to provide additional input here and we will then investigate further.
Cheers,
Sam
Comment From: spring-projects-issues
Stefan Widerin commented
Thanks for your efforts Sam.
I tried to reproduce the problem with a much simpler context now. I tried this:
package com.spring.bugtest;
// ... all imports
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@TestPropertySource(
locations = "classpath:springBug.properties",
properties = "someTask.cron=*/1 * * * * *")
@ActiveProfiles("SpringBugTest")
public class SpringBugTest
{
static boolean valueToChange = false;
@Component
public static class SomeTask implements Runnable
{
@Scheduled(cron = "${someTask.cron}")
@Override
public void run()
{
valueToChange = true;
}
}
@Test
public void testTaskIsRun() throws InterruptedException
{
Thread.sleep(3000);
Assert.assertTrue(valueToChange);
}
@Configuration
@ComponentScan(basePackages = { "com.spring.bugtest" })
@EnableScheduling
@Profile("SpringBugTest")
static class Config
{
@Bean
public static PropertySourcesPlaceholderConfigurer placeholderConfigurer()
{
return new PropertySourcesPlaceholderConfigurer();
}
}
}
But this test passes! Content of springBug.properties is someTask.cron=0 0 0 1 1 *, meaning the task would not run.
So while this works in this specific test, it doesn't in my integration test, with the full application's context. It's a spring boot application btw and trying to specify a different execution schedule for @Scheduled tasks for a certain test doesn't work for me when using inline properties, but works with another file in locations.
Could you think of a possible cause? I know that I do not explicitly create a PropertySourcesPlaceholderConfigurer bean in my app. I'd suppose that @EnableAutoConfiguration creates this bean. I can investigate further if you tell me what I can check and where.
Thanks!
Comment From: spring-projects-issues
Sam Brannen commented
Spring Boot's SpringApplicationContextLoader - which is transparently registered if you use @SpringApplicationConfiguration instead of @ContextConfiguration - processes test properties slightly different than core Spring. So that may well be the cause of the behavior you're experiencing.
What happens if you register your inlined properties via @IntegrationTest or @WebIntegrationTest instead of via @TestPropertySource?
Comment From: spring-projects-issues
Sam Brannen commented
FYI: Spring Boot automatically registers a PropertySourcesPlaceholderConfigurer for you.
Comment From: spring-projects-issues
Stefan Widerin commented
Neither @IntegrationTest("key=value") nor @WebIntegrationTest("key=value") did override the value that was loaded from the the specified properties file via @TestPropertySource(locations = ...)
Comment From: spring-projects-issues
Stefan Widerin commented
This test fails too.
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration
@TestPropertySource(
locations = "classpath:springBug.properties",
properties = "someTask.cron=*/1 * * * * *")
public class SpringBugTest {
@Value("${someTask.cron}")
private String cron;
@Test
public void testInjection() {
Assert.assertEquals("*/1 * * * * *", cron);
}
@Configuration
static class Config {
@Bean
public static PropertySourcesPlaceholderConfigurer placeholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
}
Fails with message:
org.junit.ComparisonFailure: expected:<[*/1 * * * *] *> but was:<[0 0 0 1 1] *>
So if this test should not fail, will you re-open the ticket? Maybe slightly reworded?
Comment From: spring-projects-issues
Sam Brannen commented
The source of the behavior you are experiencing lies within Spring Boot's testing support.
Although Spring Boot's testing support builds on the core support in the spring-test module, the spring-test module cannot influence how Spring Boot handles the priority of inlined properties in integration tests. In other words, this feature does in fact work as designed within core Spring. As such, I will leave this issue resolved.
However, there is already a ticket open against Spring Boot to address this topic in Spring Boot 1.4. Please see GitHub issue #4828 for details and to provide your input to the Spring Boot team.
Regards,
Sam
p.s. Phil Webb and Andy Wilkinson, this appears to be a bug in Spring Boot; whereby, Spring Boot does not honor the contract of @TestPropertySource when used with Boot's SpringApplicationContextLoader.
Comment From: spring-projects-issues
Stefan Widerin commented
Well, I have nothing to add any more I think. You cross referenced beautifully. Thanks again for looking into it.
Comment From: grimwall
I think a very similar bug is back in spring boot 2.0.2, meaning TestPropertySource does not work as expected. I have a single IT that uses TestPropertySource that works perfectly fine when run as a single test, however when I run ALL my tests the property reverts to the one defined in application.yml
Comment From: sbrannen
@grimwall, this issue was closed almost 4 years ago.
If you think you have discovered a bug in Spring Boot 2.0.x, please create a new issue in the Spring Boot issue tracker.