如何用Jest测试DatadogService.sendMetric的Promise拒绝场景
测试DatadogService.sendMetric() Promise拒绝场景的问题
问题背景
我想要测试DatadogService.sendMetric()方法的Promise拒绝场景,但运行测试后报错,相关代码和错误信息如下:
DatadogService.ts
import { client, v2 } from "@datadog/datadog-api-client"; import { getRootLogger } from "@backstage/backend-common"; import { Logger } from 'winston'; export class DatadogService { private readonly logger: Logger; apiInstance: v2.MetricsApi; constructor(apiKey : string | undefined) { const configurationOpts = { authMethods: { apiKeyAuth: apiKey }, }; const configuration = client.createConfiguration(configurationOpts); this.apiInstance = new v2.MetricsApi(configuration); this.logger = getRootLogger(); } async sendMetric(metricName: string, tags: string[]) : Promise<any> { const params: v2.MetricsApiSubmitMetricsRequest = { body: { series: [ { metric: metricName, type: 1, points: [ { timestamp: Math.round(new Date().getTime() / 1000), value: 1, }, ], tags: tags, }, ], }, }; try { await this.apiInstance.submitMetrics(params); this.logger.info(`Metric ${metricName} submitted data ${JSON.stringify(params)}`); return Promise.resolve('metric sent'); } catch(error) { this.logger.error(`Metric submission failed for ${metricName} with data ${JSON.stringify(params)}`); return Promise.reject('Error occurred while submitting metric : ' + metricName); } }; }
DatadogService.test.ts
import { DatadogService } from './DatadogService'; import { constructTagsArray } from './utils'; describe('DatadogService', () => { beforeEach(() => { jest.resetAllMocks(); }); it('send metrics to throw error due to invalid key ', async () => { const DATADOG_API_KEY = 'DUMMY_API_KEY'; const tags = { tagA: 'tagAValue', tagB: 'tagBValue' }; const response = await new DatadogService(DATADOG_API_KEY).sendMetric('datadogMetricName', constructTagsArray(tags)); const rejectMessage = 'Error occurred while submitting metric : datadogMetricName' await expect(response).rejects.toThrow(rejectMessage); }); });
测试运行错误
DatadogService › send metrics to throw error due to invalid key thrown: "Error occurred while submitting metric : datadogMetricName" 8 | }); 9 | > 10 | it('send metrics to throw error due to invalid key ', async () => { | ^ 11 | const DATADOG_API_KEY = 'DUMMY_API_KEY'; 12 | const tags = { 13 | tagA: 'tagAValue ', at service/DatadogService.test.ts:10:3 at Object.<anonymous> (service/DatadogService.test.ts:5:1)
正确的测试写法
问题出在你直接用await调用了会拒绝的Promise,导致错误直接抛出,没有被expect捕获。正确的做法是不要提前await,而是将Promise直接传入expect,通过rejects断言来验证拒绝行为。
修改后的测试代码如下:
import { DatadogService } from './DatadogService'; import { constructTagsArray } from './utils'; describe('DatadogService', () => { beforeEach(() => { jest.resetAllMocks(); }); it('send metrics to throw error due to invalid key ', async () => { const DATADOG_API_KEY = 'DUMMY_API_KEY'; const tags = { tagA: 'tagAValue', tagB: 'tagBValue' }; const rejectMessage = 'Error occurred while submitting metric : datadogMetricName'; const service = new DatadogService(DATADOG_API_KEY); // 直接对Promise使用expect.rejects断言 await expect(service.sendMetric('datadogMetricName', constructTagsArray(tags))) .rejects.toThrow(rejectMessage); }); });
额外优化建议
在async函数里,不需要手动返回Promise.resolve()或Promise.reject(),直接返回值或抛出错误即可,async函数会自动处理成Promise:
async sendMetric(metricName: string, tags: string[]) : Promise<any> { const params: v2.MetricsApiSubmitMetricsRequest = { body: { series: [ { metric: metricName, type: 1, points: [ { timestamp: Math.round(new Date().getTime() / 1000), value: 1, }, ], tags: tags, }, ], }, }; try { await this.apiInstance.submitMetrics(params); this.logger.info(`Metric ${metricName} submitted data ${JSON.stringify(params)}`); return 'metric sent'; // 直接返回值,自动包装为resolved的Promise } catch(error) { this.logger.error(`Metric submission failed for ${metricName} with data ${JSON.stringify(params)}`); throw `Error occurred while submitting metric : ${metricName}`; // 直接抛出错误,自动包装为rejected的Promise } };
内容的提问来源于stack exchange,提问作者Mahtab Alam
相关产品推荐
相关产品推荐

