如何在测试用例中动态设置Spring应用程序属性的值?

时间:2019-06-23 14:53:30

标签: spring spring-boot spring-test

让我们假设在Spring Boot应用程序中,我在application.yaml下有一个测试src/test/resources文件,其中包含以下属性定义:

some:
  property: ${some.property}

我们还假设我的测试类如下:

@RunWith(SpringRunner.class)
@SpringBootTest
public class PortServiceTest {

    @ClassRule
    public static MyClassRule classRule = new MyClassRule()

    @Autowired
    private MyDependency dependency;

    @Test
    public void shouldPopulateEnvironmentWithWiremockPort() {
        // test body
    }

}

其中MyClassRule有一个名为ruleValue()的方法,该方法进行一些计算并返回给定值:

public class MyClassRule {
    public int ruleValue() {
         // some calculations
         return value;
    }
}

我想将${some.property}的值设置为MyClassRule.ruleValue()的返回值,然后再将依赖项注入测试并开始测试-甚至可能在初始化Spring上下文之前。

我认为我可以使用自定义测试执行监听器:

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;
            }
        }
    }
}

但是:

  1. 在执行测试执行侦听器中的代码时,上下文已经初始化,并且由于${some.property}无法解析,测试甚至没有机会执行
  2. 我不确定如何向环境中注入${some.property}

那么如何以一种优雅,透明且可重用的方式将${some.property}的值设置为MyClassRule.ruleValue()的返回值?

1 个答案:

答案 0 :(得分:1)

Spring ReflectionTestUtils是基于反射的实用程序方法的集合,用于单元测试和集成测试方案。

使用ReflectionTestUtils.setField,应该能够在“ targetClass”上设置带有值的字段(在其中注入值)。

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