Behrang Saeedzadeh
Behrang Saeedzadeh

Reputation: 47913

How to set the value of a Spring application property dynamically in test cases?

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:

  1. 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
  2. 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?

Upvotes: 0

Views: 1620

Answers (1)

MrKulli
MrKulli

Reputation: 769

Spring ReflectionTestUtils is a collection of reflection-based utility methods for use in unit and integration testing scenarios.

Using ReflectionTestUtils.setField, you should be able to set field (where you injecting value) with value on the "targetClass".

@Before
public void setup(){
ReflectionTestUtils.setField(classRule , "fieldName", value);
}

Upvotes: 2

Related Questions