Spring Boot Cucumber 测试无法解析占位符 'random.uuid'
Spring Boot Cucumber tests could not resolve placeholder 'random.uuid'
我希望 Spring Boot 属性 默认情况下无法猜测随机值(出于安全原因),所以我尝试使用 random UUID 作为默认值值,使用如下代码:
@Service
public class UserServiceImpl implements UserService {
...
@Autowired
public UserServiceImpl(@NonNull final PasswordEncoder passwordEncoder,
@NonNull final UserRepository userRepository,
@NonNull @Value("${administrator.password:${random.uuid}}") final String administratorPassword) {
...
}
但是我的 Cucumber Spring 引导测试抱怨 ${random.uuid}
因此:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userServiceImpl' defined in file [.../UserServiceImpl.class]: Unexpected exception during bean creation; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'random.uuid' in value "administrator.password:${random.uuid}"
我需要做什么才能让我的应用程序使用随机 属性 值?
${random.uuid}
只能在 RandomValuePropertySource
可用时使用。
作为解决方法,您可以定义一个“虚拟默认值”并在您的代码中检测到它:
@Autowired
public UserServiceImpl(@NonNull final PasswordEncoder passwordEncoder,
@NonNull final UserRepository userRepository,
@NonNull @Value("${administrator.password:no-default-vale-provided}") final String administratorPassword) {
this.adminPassword = "no-default-value-provided".equals(administratorPassword)
? UUID.randomUUID().toString()
: administratorPassword;
}
如果您有 [`RandomValuePropertySource`](https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/env/RandomValuePropertySource.html) 可用,那么 SpEL 表达式 `${random.uuid}` 应该确实解析到一个随机的 UUID。 `${...}` 是 属性 占位符,`#{$...}` 是 SpEL 语法。
您需要更改注释:
@NonNull @Value("#{${administrator.password} ?: ${random.uuid}}") final String administratorPassword
问题可能与测试切片有关。如果我 运行 一个干净的 Spring 启动项目测试:
@SpringBootTest
class DemoApplicationTests {
@Value("${nonexistingValue:${random.uuid}}")
private String someVal;
@Test
public void someTest() {
assertThat(someVal).contains("-");
}
}
测试通过。但是,如果我将 @SpringBootTest
更改为 @ExtendWith({SpringExtension.class})
或 @RunWith(SpringRunner.class)
,测试将失败。 ${random.uuid}
和类似的表达式应该在正常的 运行 时间环境中可用。
因为这个切片,似乎 RandomValuePropertySource
不可用。一个相当不优雅的解决方法是使用在测试上下文中创建的 PropertySourcesPlaceholderConfigurer
bean 将它显式添加到上下文中:
@Configuration
public class CucumberBeansConfiguration {
@Bean
public PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
final var configurer = new PropertySourcesPlaceholderConfigurer();
final var sources = new MutablePropertySources();
sources.addFirst(new RandomValuePropertySource());
configurer.setPropertySources(sources);
return configurer;
}
}
Cucumber 使用弹簧 TestContextManager
。通过使用 @CucumberContextConfiguration
注释您的上下文配置,Cucumber 知道 class 使用哪个来启动测试上下文。
import com.example.app;
import org.springframework.boot.test.context.SpringBootTest;
import io.cucumber.spring.CucumberContextConfiguration;
@CucumberContextConfiguration
@SpringBootTest
public class CucumberSpringConfiguration {
}
确保 CucumberSpringConfiguration
在 cucumber.glue
路径上。
我希望 Spring Boot 属性 默认情况下无法猜测随机值(出于安全原因),所以我尝试使用 random UUID 作为默认值值,使用如下代码:
@Service
public class UserServiceImpl implements UserService {
...
@Autowired
public UserServiceImpl(@NonNull final PasswordEncoder passwordEncoder,
@NonNull final UserRepository userRepository,
@NonNull @Value("${administrator.password:${random.uuid}}") final String administratorPassword) {
...
}
但是我的 Cucumber Spring 引导测试抱怨 ${random.uuid}
因此:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userServiceImpl' defined in file [.../UserServiceImpl.class]: Unexpected exception during bean creation; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'random.uuid' in value "administrator.password:${random.uuid}"
我需要做什么才能让我的应用程序使用随机 属性 值?
${random.uuid}
只能在 RandomValuePropertySource
可用时使用。
作为解决方法,您可以定义一个“虚拟默认值”并在您的代码中检测到它:
@Autowired
public UserServiceImpl(@NonNull final PasswordEncoder passwordEncoder,
@NonNull final UserRepository userRepository,
@NonNull @Value("${administrator.password:no-default-vale-provided}") final String administratorPassword) {
this.adminPassword = "no-default-value-provided".equals(administratorPassword)
? UUID.randomUUID().toString()
: administratorPassword;
}
您需要更改注释:
@NonNull @Value("#{${administrator.password} ?: ${random.uuid}}") final String administratorPassword
问题可能与测试切片有关。如果我 运行 一个干净的 Spring 启动项目测试:
@SpringBootTest
class DemoApplicationTests {
@Value("${nonexistingValue:${random.uuid}}")
private String someVal;
@Test
public void someTest() {
assertThat(someVal).contains("-");
}
}
测试通过。但是,如果我将 @SpringBootTest
更改为 @ExtendWith({SpringExtension.class})
或 @RunWith(SpringRunner.class)
,测试将失败。 ${random.uuid}
和类似的表达式应该在正常的 运行 时间环境中可用。
因为这个切片,似乎 RandomValuePropertySource
不可用。一个相当不优雅的解决方法是使用在测试上下文中创建的 PropertySourcesPlaceholderConfigurer
bean 将它显式添加到上下文中:
@Configuration
public class CucumberBeansConfiguration {
@Bean
public PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
final var configurer = new PropertySourcesPlaceholderConfigurer();
final var sources = new MutablePropertySources();
sources.addFirst(new RandomValuePropertySource());
configurer.setPropertySources(sources);
return configurer;
}
}
Cucumber 使用弹簧 TestContextManager
。通过使用 @CucumberContextConfiguration
注释您的上下文配置,Cucumber 知道 class 使用哪个来启动测试上下文。
import com.example.app;
import org.springframework.boot.test.context.SpringBootTest;
import io.cucumber.spring.CucumberContextConfiguration;
@CucumberContextConfiguration
@SpringBootTest
public class CucumberSpringConfiguration {
}
确保 CucumberSpringConfiguration
在 cucumber.glue
路径上。