我遇到了一个关于从一个服务获取JWT令牌并在一个服务的测试方法中使用它的问题。
在我的spring boot微服务示例中,我尝试在支付、产品和订单服务中编写JUnit Controller test,在我定义了auth服务来处理创建用户和使用jwttoken登录,并定义了api网关来使用JWTFilter之后,需要为每个测试请求方法的每个请求定义bearer token。
通常,它的工作,但我必须得到jwt令牌和使用它,但我不知道如何得到它?
下面是PaymentControllerTest的一个测试方法,可以看到没有定义Authorization Bearer,如何定义?
@Test
@DisplayName("Place Order -- Success Scenario")
void test_When_placeOrder_DoPayment_Success() throws Exception {
OrderRequest orderRequest = getMockOrderRequest();
String jwt = getJWTTokenForRoleUser();
MvcResult mvcResult
= mockMvc.perform(MockMvcRequestBuilders.post("/order/placeorder")
.contentType(MediaType.APPLICATION_JSON_VALUE)
.header("Authorization", "Bearer " + jwt)
.content(objectMapper.writeValueAsString(orderRequest)))
.andExpect(MockMvcResultMatchers.status().isOk())
.andReturn();
String orderId = mvcResult.getResponse().getContentAsString();
Optional<Order> order = orderRepository.findById(Long.valueOf(orderId));
assertTrue(order.isPresent());
Order o = order.get();
assertEquals(Long.parseLong(orderId), o.getId());
assertEquals("PLACED", o.getOrderStatus());
assertEquals(orderRequest.getTotalAmount(), o.getAmount());
assertEquals(orderRequest.getQuantity(), o.getQuantity());
}
以下是有关jwt令牌处理的方法。
private String getJWTTokenForRoleUser(){
var loginRequest = new LoginRequest("User1","user1");
String jwt = jwtUtils.generateJwtToken(loginRequest.getUsername());
return jwt;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class LoginRequest {
private String username;
private String password;
}
下面是jwtutil类
@Component
public class JwtUtils {
private static final Logger LOGGER = LoggerFactory.getLogger(JwtUtils.class);
@Value("${jwt.secret}")
private String jwtSecret;
@Value("${jwt.expireMs}")
private int jwtExpirationMs;
public String generateJwtToken(String username) {
return generateTokenFromUsername(username);
}
public String generateTokenFromUsername(String username) {
return Jwts.builder().setSubject(username).setIssuedAt(new Date())
.setExpiration(new Date((new Date()).getTime() + jwtExpirationMs))
.signWith(SignatureAlgorithm.HS512, jwtSecret).compact();
}
}
要运行应用程序,**1)**运行服务注册表(Eureka服务器)
- 2)**运行配置服务器
- 3)**在docker上通过以下命令运行zipkin和redis
docker run -d -p 9411:9411 openzipkin/zipkin
docker run -d --name redis -p 6379:6379 redis
- 4)**运行api网关
- 5)**运行认证服务、产品服务、订单服务和支付服务
- 已编辑**(我在application-test. yaml中定义了所有属性,但无法从OrderControllerTest中提取它们)
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'jwt.secret' in value "${jwt.secret}"
下面是回购协议:Link
2条答案
按热度按时间628mspwn1#
您可以创建一个UTIL,并从那里获得一个令牌,然后在您的测试用例中使用
6fe3ivhb2#
您不能使用模拟的JWT编写服务间测试:JWT已签名,您将无法访问授权服务器私钥。
要么写
@webMvcTest
或@SpringBootTest(webEnvironment = WebEnvironment.MOCK)
,在这种情况下,应该模拟对其他服务的调用(使用wire mock或其他方法),因此将在测试安全上下文中进行身份验证(在这种情况下,根本没有JWT)第二种解决方案显然更复杂,学习、设置和维护时间更长。而且,测试速度更慢,也更脆弱。广泛的“完全”集成测试是一个地狱,经常被认为是最糟糕的做法。
Your project甚至不接近运行集成测试(没有父POM来管理模块间依赖关系和集成测试配置,缺少已配置的模块...)
从单元测试开始:@WebMvcTest用于单个@Controller,@MockBean用于已使用的@Services和@Repository等组件
然后编写一个微服务范围内的集成测试:@SpringBoot使用wirerock进行测试,以模拟与其他微服务的交换。
也许只有到那时,您才能编写涉及多个微服务、一个授权服务器和一个“富”或REST客户端(如果您想模拟用户,则使用一个实用程序方法来遍历授权代码流)的完整集成测试。
现在,我强烈建议您关注those tutorials之后的前两种测试。samples of the same repo还演示了如何使用安全表达式为@Services和@Repository编写单元测试。