Let's assume that in a Spring Boot application, I have a test application.yaml file under src/test/resources that contains the following property definition:
some:
property: ${some.property}
Also let's suppose that my test class looks like this:
@RunWith(SpringRunner.class)
@SpringBootTest
public class PortServiceTest {
@ClassRule
public static MyClassRule classRule = new MyClassRule()
@Autowired
private MyDependency dependency;
@Test
public void shouldPopulateEnvironmentWithWiremockPort() {
// test body
}
}
where MyClassRule has a method named ruleValue() that makes some calculations and returns a given value:
public class MyClassRule {
public int ruleValue() {
// some calculations
return value;
}
}
I want to set the value of ${some.property} to the return value of MyClassRule.ruleValue() before the dependencies are injected to the test and the tests start -- probably even before the Spring context is initialized.
I thought I can use a custom test execution listener:
public class CustomTestExecutionListener extends AbstractTestExecutionListener {
@Override
public void beforeTestClass(TestContext testContext) throws Exception {
Class<?> testClass = testContext.getTestClass();
Field[] fields = testClass.getFields();
for (Field field : fields) {
if (field.getType() == MyClassRule.class) {
ClassRule annotation = field.getAnnotation(ClassRule.class);
if (annotation == null) {
continue;
}
MyClassRule myClassRule = (MyClassRule) field.get(testClass);
int ruleValue = myClassRule.ruleValue();
ApplicationContext context = testContext.getApplicationContext();
Environment environment = context.getEnvironment();
// how to set {some.value} in environment?
break;
}
}
}
}
but:
- By the time the code in the test execution listener is executed, the context is already initialized and the test will have no chance to even execute as
${some.property}cannot be resolved - I am not sure how can I inject
${some.property}into the environment.
So how can I set the value of ${some.property} to the return value of MyClassRule.ruleValue() in an elegant, transparent, and reusable way?