我正在尝试学习 Spring Boot,并且我试图对测试有一个扎实的了解。
我知道 @SpringBootTest 加载了完整的上下文,我不想这样做。 我知道切片测试(即:@WebMvcTest、@JdbcTest)内部使用@ExtendWith(SpringExtension.class), 如果我只想使用自己的 bean 进行简单的集成测试,并且还想加载配置属性,是否可以将其与 @Value 一起使用?
我知道我可以使用 ReflectionTestUtils,但我想既然 Spring Extension 加载了一个测试上下文,它应该获取 application.properties 文件?
到目前为止,我用@Value得到了一个非常奇怪的结果,它获取的是键而不是值。它与 @SpringBootTest 完美配合,所以我知道在完整应用程序时属性加载得很好。
这是我的代码:
src/test/resources 中的application.properties:
misc.test-prop-value=testPropValue
@ExtendWith(SpringExtension.class) 公共类 ConfigPropertiesTest {
@Value( value = "${misc.test-prop-value}")
private String testPropValue;
@Value("${some.non.existent.value}")
private String nonExistentValue;
@Test
void testNonExistentValue() {
assertNull(nonExistentValue); // Fails, the value is: ${some.non.existent.value}
}
@Test
public void testConfigProperties() {
assertEquals("testPropValue", testPropValue); //Fails, the value is: ${misc.test-prop-value}
}
}
为什么@Value 自己获取密钥?
它与@SpringBootTest完美配合,
我想既然@SpringExtension加载了应用程序上下文:
@ExtendWith(SpringExtension.class)
public class SpringExtensionBasicTest {
@Autowired
private ApplicationContext applicationContext;
@Test
void contextLoads() throws Exception {
//GenericApplicationContext instance:
System.out.println("Context instance: " + applicationContext.getClass());
assertNotNull(applicationContext); // Test passes
}
}
当我扩展具有@SpringBootTest的基类时, 一切正常,它加载上下文,甚至在找不到 some.non.existent.value 属性时出现错误。 但使用 Spring 扩展时,行为很奇怪。
也许这是一个愚蠢的问题,我可以感觉到这是其中之一,我在脸上遗漏了一些如此明显的东西,以至于没有人解释它,但我不明白。 另外,如果我想要自己的切片测试,但我仍然希望像 @JdbcTest 一样加载 .properties 文件,那么这将如何工作
编辑:
使用@TestPropertySource时,我通过了两个测试,但是@SpringBootTest中不存在的值为null的值仍然显示相同的键:
@ExtendWith(SpringExtension.class)
@TestPropertySource(value = "classpath:application.properties")
public class ConfigPropertiesTest {
@Value( value = "${misc.test-prop-value}")
private String testPropValue;
@Value("${family.mother}")
private String mamaValue;
/**
* When a non-existent value is there,
* It is not null for some strange reason,
* But it still shows the key
*/
@Value("${some.non.existent.value}")
private String nonExistentValue;
@Test
void testNonExistentValue() {
//Still shows ${some.non.existent.value}
assertNull(nonExistentValue);
}
@Test
void testPropValue1() {
assertEquals("Mama-test", mamaValue); //Ok
}
@Test
public void testConfigProperties() {
assertEquals("testPropValue", testPropValue); //Ok
}
}
我认为您的 IgnoreUnresolvablePlaceholders 参数设置为 true。否则,缺少
${some.non.existent.value}
属性将导致错误
java.lang.IllegalArgumentException: Could not resolve placeholder 'some.non.existent.value' in value "${some.non.existent.value}"
。
例如,如果您创建这样的 bean:
@Bean
public PropertySourcesPlaceholderConfigurer propertyConfig() {
PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
configurer.setIgnoreUnresolvablePlaceholders(true);
return configurer;
}
然后,如果 Spring 找不到 nonExistentValue 字段的
some.non.existent.value
属性,它将把值 "${some.non.existent.value}"
写入该字段。
我认为您使用以下代码为 nonExistentValue 字段设置默认值是有意义的:
@Value("${some.non.existent.value:#{null}}")
private String nonExistentValue;