如何在 nest HttpService 上使用 jest 测试 retryWhen
How to test retryWhen with jest on nest HttpService
我的 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。成功则returnaccess_token
,失败则最多尝试5次,5次后仍不成功则抛出异常
现在我想写3个单元测试,
当 API 没有抛出错误并且 return 一个访问令牌时成功
失败6次
失败 2 次并且 return 访问令牌
测试 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);
});
我的 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。成功则returnaccess_token
,失败则最多尝试5次,5次后仍不成功则抛出异常
现在我想写3个单元测试,
当 API 没有抛出错误并且 return 一个访问令牌时成功
失败6次
失败 2 次并且 return 访问令牌
测试 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);
});