unit-testing - 如何在嵌套 HttpService 上用玩笑测试 retryWhen
问题描述
我的 NestJS 项目中有以下方法:
getAccessToken(): Observable < string > {
return this.httpService.post(`${url}/oauth2/token`, params).pipe(
retryWhen((errors) =>
errors.pipe(
delay(1000),
take(5),
(e) =>
concat(
e,
throwError(
`Error retrieving access token. Tried 5 times.`
)
)
)
),
catchError((err) => {
this.loggerService.error(err);
throw err;
}),
map((res) => res.data),
map((data) => data.access_token)
);
}
上面的代码将调用 API。成功则返回access_token
,失败最多尝试5次,5次不成功则抛出异常。
现在我想写3个单元测试,
当 API 没有抛出错误并返回访问令牌时成功
失败6次
失败 2 次并返回访问令牌
测试1:
it('should return access_token', async () => {
const response: AxiosResponse = {
data: {
access_token: 'token1'
},
status: 200,
statusText: 'OK',
headers: {},
config: {}
};
const post = jest
.spyOn(httpService, 'post')
.mockImplementationOnce(() => of(response));
try {
const token = await service.getAccessToken().toPromise();
expect(token).toBe('token1');
} catch (err) {
expect(true).toBeFalsy();
}
});
测试 2:
it('should retry and fails', async () => {
const err: AxiosError = {
config: {},
code: '500',
name: '',
message: '',
response: {
data: {},
status: 500,
statusText: '',
headers: {},
config: {}
},
isAxiosError: true,
toJSON: () => null
};
const post = jest
.spyOn(httpService, 'post')
.mockImplementationOnce(() => throwError(err));
try {
await service.getAccessToken().toPromise();
expect(true).toBeFalsy();
} catch (err) {
expect(err).toBe(
'Error retrieving access token. Tried 5 times.'
);
}
});
但是,我不知道如何为第 3 次编写测试。
解决方案
我找到了解决方案,以防其他人遇到同样的问题
it('should retry and return access token', async () => {
const response: AxiosResponse = {
data: {
access_token: 'token1'
},
status: 200,
statusText: 'OK',
headers: {},
config: {}
};
const err: AxiosError = {
config: {},
code: '500',
name: '',
message: '',
response: {
data: {},
status: 500,
statusText: '',
headers: {},
config: {}
},
isAxiosError: true,
toJSON: () => null
};
let retried = 0;
const post = jest
.spyOn(httpService, 'post')
.mockImplementationOnce(() => {
return new Observable((s) => {
if (retried <= 1) {
retried += 1;
s.error(err);
} else {
s.next(response);
s.complete()
}
});
});
try {
const token = await service.getAccessToken().toPromise();
expect(token).toBe('token1');
} catch (err) {
expect(true).toBeFalsy();
}
expect(post).toHaveBeenCalled();
expect(post).toHaveBeenCalledTimes(1);
});
推荐阅读
- for-loop - Findstr 在 UNC 批处理脚本上太慢了
- python - 如何在 python 中设置 powershell 的环境
- android - Android Cloud Firestore 从集合中获取少量文档的有效方法
- c# - 无需安装任何东西即可读取/写入 Excel 文件
- firebase - 如何使用 FCM 后台通知更新 UI?
- chatbot - 获取 Chat 授权令牌时出错。刷新并重试
- c# - 尝试使用 StackTrace 设置条件断点时出错
- pandas-datareader - pandas_datareader 不提取 TSP 数据
- rust - 是否可以在链接到其他库而不生成货物项目的情况下将单个 rust 文件作为脚本运行
- linux - 如何连接到 SQLPLUS 并在 ssh unix 中运行 SQL 脚本?