0

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?

1 Answer 1

2

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);
}
Sign up to request clarification or add additional context in comments.

1 Comment

Try to move ReflectionTestUtils.setField in the static block inside test class. Otherwise think about possibilities to change the source code, because if you cannot to test that code - that means you have some problems, better to rewrite or change architecture of code.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.