I came across TestPropertyValues
, which is briefly mentioned in the Spring Boot docs here: https://github.com/spring-projects/spring-boot/blob/2.1.x/spring-boot-project/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc#testpropertyvalues
It's also mentioned in the Migration Guide here: https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.0-Migration-Guide#environmenttestutils
Both examples show an environment
variable to apply the properties to, but there's no other documentation that I could find.
In my tests the property setting comes too late to affect the property injection (via @Value
) for a Spring Bean. In other words, I have a constructor like this:
public PhoneNumberAuthorizer(@Value("${KNOWN_PHONE_NUMBER}") String knownRawPhoneNumber) {
this.knownRawPhoneNumber = knownRawPhoneNumber;
}
Since the above constructor is called before the test code has a chance to run, there's no way change the property via TestPropertyValues
in the test before it's used in the constructor.
I understand that I can use the properties
parameter for @SpringBootTest
, which updates the environment before beans get created, so what's the appropriate usage of TestPropertyValues
?
The @SpringBootTest annotation is useful when we need to bootstrap the entire container. The annotation works by creating the ApplicationContext that will be utilized in our tests. We can use the webEnvironment attribute of @SpringBootTest to configure our runtime environment; we're using WebEnvironment.
The @Profile(“test”) annotation is used to configure the class when the Test cases are running. Now, you can write a Unit Test case for Order Service under the src/test/resources package.
The @SpringBootTest annotation can be used to run quick unit tests in Spring Boot.
The @SpringBootTest annotation loads the complete Spring application context. In contrast, a test slice annotation only loads beans required to test a particular layer. And because of this, we can avoid unnecessary mocking and side effects.
The Spring Boot TestEntityManager is an alternative to the standard JPA EntityManager that provides methods commonly used when writing tests. EmployeeRepository is the component that we are going to test. Now let's write our first test case:
How to Use @TestPropertySource Let's imagine we're using the value of a property by injecting it using the @Value Spring annotation: We'll then use the @TestPropertySource class-level annotation to define a new configuration source and override the value of that property:
Integration Testing With @SpringBootTest As the name suggests, integration tests focus on integrating different layers of the application. That also means no mocking is involved. Ideally, we should keep the integration tests separated from the unit tests and should not run along with the unit tests.
The spring-boot-starter-test is the primary dependency that contains the majority of elements required for our tests. The H2 DB is our in-memory database. It eliminates the need for configuring and starting an actual database for test purposes.
TestPropertyValues
isn't really designed with @SpringBootTest
in mind. It's much more useful when you are writing tests that manually create an ApplicationContext
. If you really want to use it with @SpringBootTest
, it should be possible to via an ApplicationContextInitializer
. Something like this:
@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration(initializers = PropertyTest.MyPropertyInitializer.class)
public class PropertyTest {
@Autowired
private ApplicationContext context;
@Test
public void test() {
assertThat(this.context.getEnvironment().getProperty("foo")).isEqualTo("bar");
}
static class MyPropertyInitializer
implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
TestPropertyValues.of("foo=bar").applyTo(applicationContext);
}
}
}
Spring Boot's own test make use of TestPropertyValues
quite a bit. For example, applyToSystemProperties
is very useful when you need to set system properties and you don't want them to be accidentally left after the test finishes (See EnvironmentEndpointTests for an example of that). If you search the codebase you'll find quite a few other examples of the kinds of ways it usually gets used.
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