Given I have the following 3 Beans:
@Component
public class ServiceConfig {
// This value is only available from the Spring Cloud Config Server
@Value("${example.property}")
private String exampleProperty;
public String getExampleProperty() {
return exampleProperty;
}
}
@Component
public class S1 {
int i = 1;
}
@Component
public class S2 {
@Autowired
S1 s1;
}
I want to be able to run the following test:
@RunWith(SpringRunner.class)
@SpringBootTest
public class S2Test {
@Autowired
S2 s;
@Test
public void t2() {
System.out.println(s.s1.i);
}
}
The issue I have is that since I want to test the S2
class in isolation and since it uses @Autowired
I must have a Spring context in my test, however when the Spring context is started it tries to create all 3 beans which includes the bean with @Value
. Since this value is only available from Spring Cloud Config Server the context will fail to be created giving the error: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'serviceConfig': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'example.property' in string value "${example.property}"
.
My Question is: How are properties read from Spring Cloud Config Server handled in the application when unit tests are run, observe in my test i dont even care about the config so I dont want to explicitly have to set a value in my test just for the context to be started?
I would suggest simply adding "spring.cloud.config.enabled" to false in "src/test/resources/application.properties" and adding a test value for "example.property"..
spring.cloud.config.enabled=false
example.property=testvalue
This is simple and does not impact your code base. IF needed, you could also us a MOCK web environment, and a custom test application configuration that does not include those beans.
@SpringBootTest(classes = TestOnlyApplication.class, webEnvironment = SpringBootTest.WebEnvironment.MOCK)
There is some options.
You can create test profile. Then, you will need to create application-test.yml
or application-test.properties
file. There, you can set the same value for example.property
. There, if you want to start some tests with test
profile, you can add to your test class @ActiveProfiles("test")
annotation. For these tests, test
would be started.
You can set default value for example.property
by typing @Value("${example.property:SomeDefaultValue}")
. SomeDefaultValue
will be inserted if property not found.
I'd suggest first approach. You can set proper profile with annotation and there you will make sure which profile config server will send to you.
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