如何在 Spring 启动测试中使用环境变量?
How can I use env variables with Spring Boot Test?
在我的 Spring Boot Security 应用程序中,我将我的秘密存储在文件 application.properties 中并且它可以正常工作 fine.I 可以像这样获取我的秘密密钥:
@Value("${secret}")
private String secret;
但是为了测试它并且不要在我的测试中硬编码秘密密码,我需要生成我的令牌并将其放在我的授权中header(使用 mockMvc),但我无法从测试 class 访问我的秘密环境变量,即使我在测试路径的 application.properties 文件中插入我的环境变量。
我如何为我的测试生成令牌:
public class TokenForTest {
public static String generateTokenForTest() {
Date today = new Date();
Date expireDate = new Date(today.getTime() + Long.parseLong("86400000"));
return "Bearer " + Jwts.builder()
.setIssuer("BeatSound API")
.setSubject("1")
.setIssuedAt(today)
.setExpiration(expireDate)
.signWith(SignatureAlgorithm.HS256, "secretKey")
.compact();
}
}
我是如何进行测试的:
@Test
void shouldReturnAllUsers() throws Exception {
String token = TokenForTest.generateTokenForTest();
this.mockMvc.perform(get("/api/v1/user")
.header("Authorization", token))
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk()).andDo(print())
.andExpect(jsonPath("$.[*].id").exists())
.andExpect(jsonPath("$.[*].name").exists())
.andExpect(jsonPath("$.[*].email").exists())
.andExpect(jsonPath("$.[*].password").exists())
}
在测试期间,最好只使用 src/test/resources/application-test.properties:
中的值
secret=test secret
请注意文件名,有这个“测试”后缀。这是因为 Spring 默认情况下在“测试”配置文件中启动 运行s 测试。
此属性文件是定义测试配置的地方。
选择将在测试中使用的良好示例值。
不要从环境中为测试注入示例值,因为这样做会使您的测试在一个环境中失败并在另一个环境中通过。
要为正常 运行 配置应用程序属性,请使用文件 src/main/resources/application.properties:
secret=${SECRET}
这样您就可以使用 ${ENVIRONMENT_VARIABLE_NAME}
语法将环境变量注入应用程序属性。
不像在测试 运行 期间你想要坚持具体的示例值,在你的应用程序的正常 运行 期间,最好让你的应用程序属性从 environment variables 注入。
现在,如果您像这样启动您的应用程序:
export SECRET=secretFromEnv
mvn spring-boot:run
它将以值为“secretFromEnv”的应用程序属性“secret”开始。就像您拥有它一样 secret=secretFromEnv
,但它可以在其他环境中设置不同(例如:暂存、生产)。
要在 spring 引导代码中使用应用程序 属性 值,如问题中所述,可以使用 @Value 注释:
@Service
public class MyService {
@Value("${secret}")
private String secret;
public String getSecret() {
return secret;
}
}
而这个服务的测试可以是这样的:
class MyServiceTest extends IntegrationTestRunner {
@Autowired MyService service;
@Test
public void testSecret() {
var serviceSecret = service.getSecret();
assertEquals("test secret", serviceSecret);
}
}
此测试断言应用程序配置中的示例值由服务返回。在实际运行期间,该值将从环境变量中注入,假设我们的环境变量设置为:
export SECRET=secret-from-env
然后 spring 引导应用程序在 shell:
中启动
mvn spring-boot:运行
所以现在说如果在你的休息控制器中有这样的代码:
@Autowired MyService service;
@GetMapping(path = "/secret")
@ResponseBody public String getSecret() {
return service.getSecret();
}
然后调用 HTTP GET /secret
将打印“secret-from-env”,因为这是环境变量 $SECRET 的值。
这样做:
- 允许我们拥有用于测试的示例应用程序属性;
- 对于非测试设置,值是从环境变量中注入的;
在我的 Spring Boot Security 应用程序中,我将我的秘密存储在文件 application.properties 中并且它可以正常工作 fine.I 可以像这样获取我的秘密密钥:
@Value("${secret}")
private String secret;
但是为了测试它并且不要在我的测试中硬编码秘密密码,我需要生成我的令牌并将其放在我的授权中header(使用 mockMvc),但我无法从测试 class 访问我的秘密环境变量,即使我在测试路径的 application.properties 文件中插入我的环境变量。
我如何为我的测试生成令牌:
public class TokenForTest {
public static String generateTokenForTest() {
Date today = new Date();
Date expireDate = new Date(today.getTime() + Long.parseLong("86400000"));
return "Bearer " + Jwts.builder()
.setIssuer("BeatSound API")
.setSubject("1")
.setIssuedAt(today)
.setExpiration(expireDate)
.signWith(SignatureAlgorithm.HS256, "secretKey")
.compact();
}
}
我是如何进行测试的:
@Test
void shouldReturnAllUsers() throws Exception {
String token = TokenForTest.generateTokenForTest();
this.mockMvc.perform(get("/api/v1/user")
.header("Authorization", token))
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk()).andDo(print())
.andExpect(jsonPath("$.[*].id").exists())
.andExpect(jsonPath("$.[*].name").exists())
.andExpect(jsonPath("$.[*].email").exists())
.andExpect(jsonPath("$.[*].password").exists())
}
在测试期间,最好只使用 src/test/resources/application-test.properties:
中的值secret=test secret
请注意文件名,有这个“测试”后缀。这是因为 Spring 默认情况下在“测试”配置文件中启动 运行s 测试。 此属性文件是定义测试配置的地方。 选择将在测试中使用的良好示例值。 不要从环境中为测试注入示例值,因为这样做会使您的测试在一个环境中失败并在另一个环境中通过。
要为正常 运行 配置应用程序属性,请使用文件 src/main/resources/application.properties:
secret=${SECRET}
这样您就可以使用 ${ENVIRONMENT_VARIABLE_NAME}
语法将环境变量注入应用程序属性。
不像在测试 运行 期间你想要坚持具体的示例值,在你的应用程序的正常 运行 期间,最好让你的应用程序属性从 environment variables 注入。
现在,如果您像这样启动您的应用程序:
export SECRET=secretFromEnv
mvn spring-boot:run
它将以值为“secretFromEnv”的应用程序属性“secret”开始。就像您拥有它一样 secret=secretFromEnv
,但它可以在其他环境中设置不同(例如:暂存、生产)。
要在 spring 引导代码中使用应用程序 属性 值,如问题中所述,可以使用 @Value 注释:
@Service
public class MyService {
@Value("${secret}")
private String secret;
public String getSecret() {
return secret;
}
}
而这个服务的测试可以是这样的:
class MyServiceTest extends IntegrationTestRunner {
@Autowired MyService service;
@Test
public void testSecret() {
var serviceSecret = service.getSecret();
assertEquals("test secret", serviceSecret);
}
}
此测试断言应用程序配置中的示例值由服务返回。在实际运行期间,该值将从环境变量中注入,假设我们的环境变量设置为:
export SECRET=secret-from-env
然后 spring 引导应用程序在 shell:
中启动mvn spring-boot:运行
所以现在说如果在你的休息控制器中有这样的代码:
@Autowired MyService service;
@GetMapping(path = "/secret")
@ResponseBody public String getSecret() {
return service.getSecret();
}
然后调用 HTTP GET /secret
将打印“secret-from-env”,因为这是环境变量 $SECRET 的值。
这样做:
- 允许我们拥有用于测试的示例应用程序属性;
- 对于非测试设置,值是从环境变量中注入的;