为单个Spring Boot测试覆盖属性
为单个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() { ... } }
我正在使用`SpringBootTest`注解的`properties`属性为此测试套件中的所有测试设置`some.property`属性的值。现在我想为其中一个测试(例如`testC`)设置此属性的另一个值,而不影响其他测试。我该如何实现这个目标?我已经阅读了Spring Boot文档的"Testing"章节,但没有找到符合我的用例的内容。
问题的出现原因:在Spring Boot测试中,属性在Spring上下文加载期间进行评估,因此在容器启动后无法更改它们。
解决方法:可以将方法拆分为多个类,以创建它们自己的Spring上下文。但要注意,这可能是一个不好的主意,因为测试执行应该很快。更好的方法是在被测试的类中添加一个setter方法,该方法注入some.property
值,并在测试中使用此方法来以编程方式更改该值。
以下是示例代码:
private String someProperty; ("${some.property}") public void setSomeProperty(String someProperty) { this.someProperty = someProperty; }
文章标题:如何为单个Spring Boot测试覆盖属性
在Spring Boot测试中,有时候需要为单个测试覆盖某个属性。下面是一种解决方案:
假设我们有一个方法叫做`do_stuff()`,它接受一个`MyProperties`对象作为参数。我们可以在该方法中设置属性的值,例如`properties.setSomething(...)`。
然而,如果这个方法首先运行,那么所有其他测试用例中的属性值也会被改变,这并不是我们想要的结果。
为了解决这个问题,我们可以在测试类中的`setup`方法中使用`@Autowired`注解将属性注入进来,并在该方法中设置默认值。这样,每个测试方法都会使用默认值,而不会相互影响。
下面是一个示例代码:
@SpringBootTest public class MyTest { @Autowired private MyProperties properties; @BeforeEach public void setup() { properties.setSomething("default value"); } @Test public void test1() { // Test code } @Test public void test2() { // Test code } }
通过在`setup`方法中设置默认值,我们可以确保每个测试方法都使用相同的默认值,而不会相互影响。这样,我们就可以在单个测试中覆盖某个属性,而不会影响其他测试的结果。
在Spring Boot测试中,有时候我们希望为单个测试覆盖一个属性。然而,由于Spring上下文和属性只在整个测试类加载一次,因此无法直接在测试案例C中更改属性的值。
那么,有没有办法解决这个问题呢?答案是可以的!在Spring 5.2.5和Spring Boot 2.2.6及以上版本中,有一个解决方案。
首先,我们需要定义一个静态方法dynamicProperties,该方法接收一个DynamicPropertyRegistry参数。在该方法中,我们可以使用registry.add()方法来添加我们想要覆盖的属性及其新值。示例代码如下所示:
static void dynamicProperties(DynamicPropertyRegistry registry) { registry.add("some.property", () -> "valueA"); }
接下来,在测试案例C中,我们可以调用dynamicProperties方法,并将DynamicPropertyRegistry作为参数传递给它。这样,在测试案例C中,我们就可以为属性赋予新的值。示例代码如下所示:
@Test void testCaseC(DynamicPropertyRegistry registry) { dynamicProperties(registry); // 测试逻辑 }
通过这种方式,我们就可以在单个测试案例中覆盖属性的值了。
这种解决方法的关键在于使用DynamicPropertyRegistry来动态添加属性。通过这种方式,我们可以在测试案例中覆盖属性的值,而不会影响其他测试案例或整个测试类的属性值。