SpringBootTest - 如何在测试级别断言上下文不加载和更改属性?
SpringBootTest - how to assert context not loads and change properties at test level?
我在测试应用程序配置时非常依赖 @SpringBootTest
。应用程序属性可能很复杂,具有默认值和重要的验证。例如:
prop:
ports: 1205,2303,4039
fqdn: ${server.host}:${ports[0]}/${path}
@Configuration
SomeConfigClass{
@Value{"${ports}:{#collections.emptyList}"}
List<Integer> ports;
...
}
在测试此类应用程序时,我提出了没有模拟的完整或部分应用程序上下文,因为上下文和验证本身存在复杂性 - 模拟无法捕捉到这一点。不幸的是,我不断发现这种模式有两个局限性:
我们如何测试错误的配置无法加载?
假设测试端口无效,因为它不在 500 - 1500
.
的限制范围内
@SpringBootTest(
classes = {SomeConfigClass.class},
properties = "port=9000"
)
public class BadConfigTest{
@Test(expected = ApplicationContextFailedException.class)
public void WHEN_port_9000_THEN_appcontext_fails_to_load() {}
}
由于测试框架在加载应用程序上下文之后加载应用程序上下文,因此似乎无法测试应用程序上下文加载失败。现在我实际上写了测试,手动确认它们失败了,然后用 @Ignored
注释所以它们不会丢失。
如何在测试方法而不是 class 级别更改属性?
@SpringBootTest
是一个 class 注释,意味着应用程序属性绑定在 test-class 级别。这导致需要对许多属性集进行测试 class 并使测试套件膨胀。例如,我将以测试 classes 结束,例如:
ConfigPropertiesAllValidTest
ConfigPropertiesNoneSetTest
ConfigPropertiesSomeValidSomeNotTest
其中每个只有一个或两个测试用例。最好有一个 ConfigPropertiesTest
class 每个测试都有不同的道具。这可能吗?
同样 - 我想避免模拟,因为它们不会捕获 Spring 在运行时执行的重要上下文自动配置。
您可以使用 @ActiveProfiles
注释和 @SpringBootTest
注释来加载不同配置文件的属性。这是 class 级别,因此仅对您问题的情况 1 有帮助。
@SpringBootTest(classes = {SomeConfigClass.class})
@ActiveProfiles("badconfigtest")
public class BadConfigTest{
...
}
然后application-badconfigtest.properties
你的错误配置。
我认为您找不到在同一个 class 中的测试方法之间更改属性的方法。您可以使用 @DirtiesContext 重新加载应用程序上下文,但我还没有看到使用不同 属性 文件的方法。我想您可以将这些值注入到已经加载属性的配置 classes 中。
我们最终使用了本文档中描述的 ApplicationContextRunner
:
我在测试应用程序配置时非常依赖 @SpringBootTest
。应用程序属性可能很复杂,具有默认值和重要的验证。例如:
prop:
ports: 1205,2303,4039
fqdn: ${server.host}:${ports[0]}/${path}
@Configuration
SomeConfigClass{
@Value{"${ports}:{#collections.emptyList}"}
List<Integer> ports;
...
}
在测试此类应用程序时,我提出了没有模拟的完整或部分应用程序上下文,因为上下文和验证本身存在复杂性 - 模拟无法捕捉到这一点。不幸的是,我不断发现这种模式有两个局限性:
我们如何测试错误的配置无法加载?
假设测试端口无效,因为它不在
的限制范围内500 - 1500
.@SpringBootTest( classes = {SomeConfigClass.class}, properties = "port=9000" ) public class BadConfigTest{ @Test(expected = ApplicationContextFailedException.class) public void WHEN_port_9000_THEN_appcontext_fails_to_load() {} }
由于测试框架在加载应用程序上下文之后加载应用程序上下文,因此似乎无法测试应用程序上下文加载失败。现在我实际上写了测试,手动确认它们失败了,然后用
@Ignored
注释所以它们不会丢失。如何在测试方法而不是 class 级别更改属性?
@SpringBootTest
是一个 class 注释,意味着应用程序属性绑定在 test-class 级别。这导致需要对许多属性集进行测试 class 并使测试套件膨胀。例如,我将以测试 classes 结束,例如:ConfigPropertiesAllValidTest ConfigPropertiesNoneSetTest ConfigPropertiesSomeValidSomeNotTest
其中每个只有一个或两个测试用例。最好有一个
ConfigPropertiesTest
class 每个测试都有不同的道具。这可能吗?
同样 - 我想避免模拟,因为它们不会捕获 Spring 在运行时执行的重要上下文自动配置。
您可以使用 @ActiveProfiles
注释和 @SpringBootTest
注释来加载不同配置文件的属性。这是 class 级别,因此仅对您问题的情况 1 有帮助。
@SpringBootTest(classes = {SomeConfigClass.class})
@ActiveProfiles("badconfigtest")
public class BadConfigTest{
...
}
然后application-badconfigtest.properties
你的错误配置。
我认为您找不到在同一个 class 中的测试方法之间更改属性的方法。您可以使用 @DirtiesContext 重新加载应用程序上下文,但我还没有看到使用不同 属性 文件的方法。我想您可以将这些值注入到已经加载属性的配置 classes 中。
我们最终使用了本文档中描述的 ApplicationContextRunner
: