覆盖单个Spring Boot测试的属性

kor*_*lar 8 java spring spring-boot

考虑以下示例:

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
    properties = {
        "some.property=valueA"
    })
public class ServiceTest {
    @Test
    public void testA() { ... }

    @Test
    public void testB() { ... }

    @Test
    public void testC() { ... }
}
Run Code Online (Sandbox Code Playgroud)

我正在使用SpringBootTest注释的properties属性来设置some.property此测试套件中所有测试的属性值。现在,我想为其中一个测试(假设testC)设置此属性的另一个值,而不影响其他测试。我该如何实现?我已经阅读了Spring Boot docs“测试”一章,但是没有找到与我的用例匹配的内容。

dav*_*xxx 6

在Spring上下文加载期间,Spring将评估您的属性。
因此,在容器启动后,您将无法更改它们。

解决方法是,您可以将方法拆分为多个类,从而创建自己的Spring上下文。但是要当心,因为测试执行应该很快,所以这可能不是一个好主意。

更好的方法可能是在被测类中有一个设置器来注入some.property值,然后在测试中 使用此方法以编程方式更改值。

private String someProperty;

@Value("${some.property}")
public void setSomeProperty(String someProperty) {
    this.someProperty = someProperty;
}
Run Code Online (Sandbox Code Playgroud)

  • 我不明白为了测试而改变源代码是个好主意 (10认同)
  • @ChristianVincenzoTraina 未经测试的代码很糟糕。如果代码不是以可测试的方式编写的,那么它就是不好的并且必须更改。如果您知道如何在不更改代码的情况下解决此问题,请发布答案。 (5认同)

tim*_*guy 6

更新

可以使用 Spring 5.2.5 和 Spring Boot 2.2.6

@DynamicPropertySource
static void dynamicProperties(DynamicPropertyRegistry registry) {
    registry.add("some.property", () -> "valueA");
}
Run Code Online (Sandbox Code Playgroud)


Sam*_*Sam 5

如果您使用的是另一种解决方案@ConfigurationProperties

@Test
void do_stuff(@Autowired MyProperties properties){
  properties.setSomething(...);
  ...
}
Run Code Online (Sandbox Code Playgroud)

  • 我认为如果这个方法首先运行,那么这个类中的所有其他测试也会发生变化。 (2认同)