Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add YamlPropertySourceFactory that can be used for loading YAML files through the @TestPropertySource annotation #42603

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

nosan
Copy link
Contributor

@nosan nosan commented Oct 11, 2024

I have prepared two potential solutions for this #33434 enhancement.

The first approach offers a simple and intuitive way to use it:

@SpringJUnitConfig
@TestPropertySource(locations = "classpath:test.yaml", factory = YamlPropertySourceFactory.class)
class SomeTest {

}

YamlPropertySourceFactory loads all properties from the specified YAML file using YamlPropertySourceLoader and returns a CompositePropertySource containing the loaded properties.

As a potential improvement, a dedicated annotation like @TestYamlPropertySource could be introduced to simplify the loading of YAML files in tests.

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@TestPropertySource(factory = YamlPropertySourceFactory.class)
@Repeatable(TestYamlPropertySources.class)
public @interface TestYamlPropertySource {

	@AliasFor(attribute = "value", annotation = TestPropertySource.class)
	String[] value() default {};

	@AliasFor(attribute = "locations", annotation = TestPropertySource.class)
	String[] locations() default {};

	@AliasFor(attribute = "inheritLocations", annotation = TestPropertySource.class)
	boolean inheritLocations() default true;

	@AliasFor(attribute = "properties", annotation = TestPropertySource.class)
	String[] properties() default {};

	@AliasFor(attribute = "inheritProperties", annotation = TestPropertySource.class)
	boolean inheritProperties() default true;

}

With a dedicated annotation, the following syntax could be supported:

@SpringJUnitConfig
@TestYamlPropertySource({ "classpath:test.yaml", "classpath:test1.yaml" })
@TestYamlPropertySource(locations = "classpath:test2.yaml", properties = "key:value")
class TestYamlPropertySourceIntegrationTests {

}

An alternative approach is to customize PropertySourceDescriptor in SpringBootTestContextBootstrapper by using the PropertySourceLoaderPropertySourceFactory, which leverages the existing PropertySourceLoader. With that approach, the following syntax would be possible:

@SpringBootTest
@TestPropertySource(locations = "classpath:test.yaml")
class SomeTest {
	
}

But it has several disadvantages:

  • It works only with the @SpringBootTest annotation. For @SpringJUnitConfig, the factory needs to be explicitly used.

  • It does not support EncodedResource for .properties files because PropertySourceLoader only works with Resource objects. As a result, if someone is using @TestPropertySource with the encoding attribute, these changes could potentially impact them.

  • Not obvious.

The first approach is much better and straightforward, and people would not have any problem using it.

… through the @TestPropertySource annotation.
@nosan
Copy link
Contributor Author

nosan commented Oct 14, 2024

The third option
is similar to the first approach, but instead of supporting only .yaml files, it also
supports multi-document .properties.

@SpringJUnitConfig
@TestPropertySource(locations = { "classpath:test.yaml", "classpath:test1.yaml", "classpath:test.properties" },
		factory = PropertySourceLoaderPropertySourceFactory.class)
class PropertySourceLoaderPropertySourceFactoryIntegrationTests {

}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: waiting-for-triage An issue we've not yet triaged
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants