Jest如何测试存在毫秒级差异的日期?解决测试失败问题
问题
我正在编写测试用例验证一个延长过期日期的函数,但在创建/更新数据库文档与对日期进行断言的时间点之间存在微小的毫秒级差异,导致测试失败。测试代码如下:
it('should extendExpirationDate', async () => { const document = documentBuilder.build(); await testDatabase.fillCollections({ documents: [document] }); let documents = await DocumentModel.find({}); expect(documents[0].validUntil).toBe(moment().add(90, 'days').toDate()); const documentDto: UpdateDocumentDto = { ...document, validUntil: moment().add(100, 'days').toDate(), }; await documentService.extendExpirationDate(documentDto); documents = await DocumentModel.find({}); expect(documents[0].validUntil).toBe(moment().add(100, 'days').toDate()); });
我想知道是否存在支持在误差范围内比较日期的函数?如何让这些测试用例不再失败?
我的尝试与期望:
对存在毫秒级差异的日期进行比较时测试失败。我期望当日期仅存在毫秒级差异而非天数差异时测试通过,同时希望避免如2024-06-13T23:59:59.995Z与2024-06-14T00:00:00.002Z这类跨天边缘情况的问题。
解决方案
1. 用 Moment.js 按精度比较日期
既然已经在用 Moment.js,直接用它的 isSame 方法指定比较精度到「天」,既能忽略毫秒/时分秒的微小差异,也能避免跨天的误判:
// 初始日期断言 expect(moment(documents[0].validUntil).isSame(moment().add(90, 'days'), 'day')).toBe(true); // 更新后的日期断言 expect(moment(documents[0].validUntil).isSame(moment().add(100, 'days'), 'day')).toBe(true);
'day' 表示只校验年/月/日的一致性,如果需要更精细的精度(比如小时),可以换成 'hour',但你的场景用'day'刚好匹配需求。
2. 用测试框架的误差范围断言(针对时间戳)
如果用 Jest,可将日期转成时间戳(毫秒数),用 toBeCloseTo 忽略毫秒级差异:
const expectedInitial = moment().add(90, 'days').valueOf(); expect(documents[0].validUntil.getTime()).toBeCloseTo(expectedInitial, -3); // -3 表示忽略最后三位(毫秒),只比较到秒级
注意:这种方法可能会在跨天边缘场景误判,比如差几秒刚好跨天,所以更推荐第一种方法。
3. 提前固定预期日期(根源避免差异)
在测试开始前就生成固定的预期日期,避免每次调用 moment().add() 生成新时间(哪怕只差几毫秒):
it('should extendExpirationDate', async () => { // 固定到当天起始时间,消除毫秒差异 const initialValidUntil = moment().add(90, 'days').startOf('day').toDate(); const extendedValidUntil = moment().add(100, 'days').startOf('day').toDate(); // 用固定日期构建文档 const document = documentBuilder.build({ validUntil: initialValidUntil }); await testDatabase.fillCollections({ documents: [document] }); let documents = await DocumentModel.find({}); expect(moment(documents[0].validUntil).isSame(initialValidUntil, 'day')).toBe(true); const documentDto: UpdateDocumentDto = { ...document, validUntil: extendedValidUntil, }; await documentService.extendExpirationDate(documentDto); documents = await DocumentModel.find({}); expect(moment(documents[0].validUntil).isSame(extendedValidUntil, 'day')).toBe(true); });
这种方式从根源上消除了时间差问题,因为预期日期是提前固定的,不会随测试执行时间变化。
内容的提问来源于stack exchange,提问作者André
相关产品推荐
相关产品推荐

