java - 如何在 JUnit 5 Java 中模拟 JsonWebToken 库
问题描述
我有一个返回 JsonWebToken 的身份验证服务。
首先,它验证提供的令牌,读取声明,然后根据该数据生成一个新的。
以下是执行特定操作的方法:
@Override
public String authenticate(String appName, String zendeskJwt) {
String zendeskPublicKeyString = zendeskService.getAppPublicKey(appName);
RSAPublicKey zendeskPublicKey = asymmetricKeyParser.publicKey(zendeskPublicKeyString);
Jws<Claims> parsedZendeskJws = Jwts.parserBuilder()
.setSigningKey(zendeskPublicKey)
.build()
.parseClaimsJws(zendeskJwt);
String zendeskUserReference = parsedZendeskJws.getBody().getSubject();
ZendeskUser zendeskUser = zendeskService.getZendeskUser(zendeskUserReference);
Date currentTime = new Date(System.currentTimeMillis());
Date expirationTime = new Date(currentTime.getTime() + cspExciteJwtProperties.getExpirationDuration().toMillis());
RSAPrivateKey cspPrivateKey = asymmetricKeyParser.privateKey(cspExciteJwtProperties.getPrivateKey());
return Jwts.builder()
.setIssuedAt(currentTime)
.setExpiration(expirationTime)
.claim(CLAIM_ZENDESK_AGENT_ID, zendeskUser.getId())
.claim(CLAIM_HYDRA_USER_ID, zendeskUser.getExternalId())
.signWith(cspPrivateKey)
.compact();
}
代码本身工作得很好。我的问题是关于单元测试。我想测试这个方法。
我试图检查很多材料,但没有一个对我有用。据消息人士透露,每个人都说嘲笑图书馆本身并不是一个好主意。但我不太确定如何在不模拟 Jwt 库的情况下通过单元测试。我有集成测试,这是一个不同的场景。对于单元测试,我不应该提出任何真正的要求。
这是我到目前为止尝试过的
private RSAPrivateKey privateKey() throws NoSuchAlgorithmException, InvalidKeySpecException {
String parsedPrivateKey = PRIVATE_KEY
.replace("-----BEGIN PRIVATE KEY-----", "")
.replace("-----END PRIVATE KEY-----", "")
.replaceAll("\\n", "").trim();
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
var decoded = Base64.getDecoder().decode(parsedPrivateKey);
PKCS8EncodedKeySpec keySpecPKCS8 = new PKCS8EncodedKeySpec(decoded);
return (RSAPrivateKey) keyFactory.generatePrivate(keySpecPKCS8);
}
private String generateJwt() throws InvalidKeySpecException, NoSuchAlgorithmException {
RSAPrivateKey cspPrivateKey = privateKey();
System.out.println(cspPrivateKey);
Duration expirationDuration = Duration.parse("PT20M");
Date currentTime = new Date(System.currentTimeMillis());
Date expirationTime = new Date(currentTime.getTime() + expirationDuration.toMillis());
return Jwts.builder()
.setIssuedAt(currentTime)
.setExpiration(expirationTime)
.claim(CLAIM_ZENDESK_AGENT_ID, 123)
.claim(CLAIM_HYDRA_USER_ID, "123")
.signWith(cspPrivateKey)
.compact();
}
@Test
void authenticate() throws InvalidKeySpecException, NoSuchAlgorithmException {
String appName = "appName";
String zendeskJwt = generateJwt();
RSAPublicKey zendeskPublicKey = new AsymmetricKeyParser().publicKey(PUBLIC_KEY);
ZendeskUser zendeskUser = new ZendeskUser(123, "123");
Jws<Claims> jws = new Jws<Claims>() {
@Override
public JwsHeader getHeader() {
return null;
}
@Override
public Claims getBody() {
return null;
}
@SneakyThrows
@Override
public String getSignature() {
return generateJwt();
}
};
when(zendeskService.getAppPublicKey(appName)).thenReturn(String.valueOf(zendeskPublicKey));
// This is how I am trying to mock JWT
when(Jwts.parserBuilder()
.setSigningKey(zendeskPublicKey)
.build()
.parseClaimsJws(zendeskJwt)).thenReturn(jws);
when(zendeskService.getZendeskUser("//example.com")).thenReturn(zendeskUser);
testObj.authenticate(appName, zendeskJwt);
}
它给了我这个错误
org.mockito.exceptions.misusing.MissingMethodInvocationException:
when() requires an argument which has to be 'a method call on a mock'.
For example:
when(mock.getArticles()).thenReturn(articles);
Also, this error might show up because:
1. you stub either of: final/private/equals()/hashCode() methods.
Those methods *cannot* be stubbed/verified.
Mocking methods declared on non-public parent classes is not supported.
2. inside when() you don't call method on mock but on some other object.
欢迎任何建议。
解决方案
推荐阅读
- erc20 - 创建 CREDITS 错误:错误:[ethjs-rpc] rpc 错误,有效载荷 {"id":291279815469,"jsonrpc":"2.0","params"
- node.js - Lusca csrf 未按预期工作 - 使用旧令牌的 http 请求
- ruby-on-rails - Completed 401 Unauthorized - 设计 devise_parameter_sanitizer 不允许任何值
- ios - Swift 中两个字符之间的差异(引号与智能/卷曲引号)
- python - Python 加速 Pytesseract / 在 Python 中使用原生 tesseract 库
- ms-office - 我们如何发布不支持 IE 的 office 插件?
- sql - 如果满足某些特定条件,如何将表格形式的数据插入另一个表格
- xamarin - appcenter 没有 **push** 选项?
- ios - 有没有结合 NSSet 和 FetchResult<> 的函数
- kubernetes - 在新创建的 kubernetes 集群中启动 POD 时出错 (ContainerCreating)