【问题标题】:How can I use env variables with Spring Boot Test?如何在 Spring Boot Test 中使用环境变量?
【发布时间】:2021-09-29 07:59:00
【问题描述】:

在我的 Spring Boot Security 应用程序中,我将我的密钥存储在文件 application.properties 中,它工作得很好。我可以像这样获取我的密钥:

@Value("${secret}")
private String secret;

但是为了测试它并且不要在我的测试中硬编码密码,我需要生成我的令牌并将其放在我的授权标头上(使用 mockMvc),但我可以'不要从测试类访问我的秘密环境变量,即使我将我的环境变量插入到测试路径的 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())
        }

【问题讨论】:

标签: java spring-boot testing jwt spring-boot-test


【解决方案1】:

在测试期间,最好只使用来自 src/test/resources/application-test.properties 的值:

secret=test secret

请注意文件名,有这个“测试”后缀。它在那里是因为 Spring Boot 默认在“test”配置文件中运行测试。 此属性文件是定义您的测试配置的地方。 选择将在您的测试中使用的好的示例值。 不要从环境中为测试注入示例值,因为这样做会使您的测试在一个环境中失败并在另一个环境中通过。

要为正常运行配置应用程序属性,请使用文件 src/main/resources/application.properties:

secret=${SECRET}

通过这种方式,您可以使用${ENVIRONMENT_VARIABLE_NAME} 语法将环境变量注入应用程序属性。 与在测试运行期间您要坚持具体示例值不同,在应用程序的正常运行期间,最好让您的应用程序属性从environment variables 注入。 现在,如果您像这样启动您的应用程序:

export SECRET=secretFromEnv
mvn spring-boot:run

它将从具有值“secretFromEnv”的应用程序属性“secret”开始。就像您拥有 secret=secretFromEnv 一样,但它可以在其他环境中进行不同的设置(例如:登台、生产)。

要在你的spring boot代码中使用应用程序属性值,如问题中所述,可以使用@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

然后在这个shell中启动spring boot应用程序:

mvn spring-boot:run

所以现在说如果在你的休息控制器中有这样的代码:

@Autowired MyService service;

@GetMapping(path = "/secret")
@ResponseBody public String getSecret() {
  return service.getSecret();
}

然后调用 HTTP GET /secret 将打印“secret-from-env”,因为这是环境变量 $SECRET 的值。

这样做:

  • 允许我们拥有用于测试的示例应用程序属性;
  • 对于非测试设置,这些值是从环境变量中注入的;

【讨论】:

    猜你喜欢
    • 2016-06-26
    • 2021-11-09
    • 1970-01-01
    • 2021-02-09
    • 2019-08-03
    • 1970-01-01
    • 2020-06-09
    • 2017-09-06
    • 2020-03-15
    相关资源
    最近更新 更多