日期单元测试本地通过但Azure Pipeline中失败的原因排查
问题:Jest测试本地通过但Azure Pipeline中失败
背景
我编写了Jest单元测试验证format2APIDate函数,本地执行npm run test所有用例都通过,但合并代码后,最后一个测试用例在Azure Pipeline中失败。
测试代码
import { describe, expect, it } from "@jest/globals" import { format2APIDate } from "../helpers" describe("format2APIDate()", () => { it("should return a date with the format: YYYY/MM/DD for date with this format YYYY-MM-DD", () => { const date = new Date("2024-02-12") const formattedDate = format2APIDate(date) expect(formattedDate).toBe("2024/02/12") }) it("should return a date with the format: YYYY/MM/DD when a date has this format", () => { const date = new Date("Mon Feb 12 2024 00:00:00 GMT+0100 (Central European Standard Time)") const formattedDate = format2APIDate(date) expect(formattedDate).toBe("2024/02/12") }) })
函数实现
export const format2APIDate = (date: Date) => { // Format the date as "YYYY/MM/DD" const formattedDate = new Date(date) return `${formattedDate.getFullYear()}/${String(formattedDate.getMonth() + 1).padStart(2, "0")}/${String(formattedDate.getDate()).padStart(2, "0")}` }
问题根源
核心是时区差异:
- 本地测试时,你的机器时区和日期字符串里的GMT+0100一致,解析后
getDate()返回12号,符合预期。 - Azure Pipeline默认使用UTC时区(GMT+0000),解析
Mon Feb 12 2024 00:00:00 GMT+0100时,会转换为UTC时间的2024-02-11 23:00:00,此时getDate()返回11号,导致断言失败。
解决办法
1. 改用UTC日期方法
修改函数,使用UTC版本的日期获取方法,确保不受运行环境时区影响:
export const format2APIDate = (date: Date) => { const formattedDate = new Date(date) return `${formattedDate.getUTCFullYear()}/${String(formattedDate.getUTCMonth() + 1).padStart(2, "0")}/${String(formattedDate.getUTCDate()).padStart(2, "0")}` }
注意:如果业务需求是取原日期的本地日期而非UTC,这个方案可能不适用,需要同步调整测试预期值。
2. 统一测试环境时区
强制Jest在UTC时区运行测试,同时调整对应测试预期值:
- 修改Jest配置
在jest.config.js中添加:
module.exports = { // 其他配置项 testEnvironmentOptions: { timezone: 'UTC', }, };
然后把第二个测试用例的预期值改成"2024/02/11"(原日期转换为UTC后是2月11号)。
- 临时设置时区
在测试文件顶部添加:
process.env.TZ = 'UTC';
同样需要对应调整测试预期值,确保和时区匹配。
3. 使用成熟日期库(推荐)
手动处理日期格式化容易踩时区坑,建议使用date-fns或moment.js这类专业日期库:
以date-fns为例:
import { format } from 'date-fns'; export const format2APIDate = (date: Date) => { return format(date, 'yyyy/MM/dd'); }
如果需要指定时区,可以配合date-fns-tz扩展,确保不同环境下结果完全一致。
内容的提问来源于stack exchange,提问作者Ala Eddine Menai
相关产品推荐
相关产品推荐

