✗ npx jest --version
24.5.0
获得了一组对时区敏感的玩笑测试。我们通常使用npm脚本运行它们:"jest": "TZ=utc jest"
将TZ设置为utc时,我会在快照中获得如下所示的值:
modificationDate="2019-01-08T00:00:00.000Z"
没有它我得到:
modificationDate="2019-01-08T08:00:00.000Z"
有没有一种方法可以在我的jest配置中进行设置,以便我可以在命令行中运行npx jest
而不用通过NPM脚本? {{3}中没有任何内容}。
我尝试将这两个添加到我的jest.config.js中。没有人起作用:
TZ: 'utc',
globals: {
TZ: 'utc',
},
当然,解决这个问题似乎微不足道,但令我感到惊讶的是,Jest没有办法配置它进行测试。
答案 0 :(得分:5)
process.env.TZ = 'UTC';
的问题在于,如果某行在此行之前运行并使用Date
,则该值将被缓存在Date
中。因此,process.env
通常不适合设置时区。参见https://github.com/nodejs/node/issues/3449
因此,更好的方法是使用实际的env变量,但是对于测试而言,它将起作用:
1。将此添加到您的package.json
"jest": {
...
"globalSetup": "../global-setup.js"
}
}
2。将此文件放在package.json 之外,作为global-setup.js
module.exports = async () => {
process.env.TZ = 'UTC';
};
3。可选:添加一个测试以确保UTC执行
describe('Timezones', () => {
it('should always be UTC', () => {
expect(new Date().getTimezoneOffset()).toBe(0);
});
});
正常的setupFiles
对我不起作用,因为它们运行得太晚了(开玩笑:^ 23.5.0)。因此,使用globalSetup文件是强制性。
答案 1 :(得分:5)
如果您正在使用npm脚本(即npm run test
)运行测试,则可以像这样传递时区:
"scripts": {
"test": "TZ=UTC jest"
},
我个人还认为,在远程CI服务器上调试问题时,此方法(与process.env
方法相比)更干净,更容易识别时区。
答案 2 :(得分:4)
更新:这不会产生确定性结果如果您想动态更改 TZ,但如果您只想要一个 TZ,它会起作用。这可能是在脚本级别指定的替代方法,但我认为这将是更好的答案。
问题在于,通过在运行时设置 process.env.TZ
,它会在常规 Jest 测试运行期间跨测试产生不确定性行为(副作用)。如果您使用连续运行测试的 --runInBand
,它可能工作,但我不会指望它。
我还在 Node 中发现了一个关于动态时区的旧存档问题,它看起来像 dynamically adjusting it won't work in general。
相反,我可能最终会得到多个脚本,每个脚本在启动 TZ
之前都设置了 jest
。
对于我的用例,我实际上想在不同时区下针对特定的基于日期的边缘情况运行测试。有时用户会遇到基于时区的错误,我们希望在我们的测试套件中轻松解决这个问题。
默认情况下,我们使用此处建议的答案之一运行项目中的所有测试,方法是在 TZ=UTC
脚本中设置 npm
(例如 TZ=UTC npm run jest
。这将在 UTC 下运行所有测试时区。
然后,我们利用可以使用 JSDoc pragma testEnvironment
在测试套件级别设置的 @jest-environment
配置。使用此自定义测试环境,然后我们可以使用“自定义文档块编译指示”(如 @timezone
)读取套件所需的时区。这使每个测试套件的时区自定义成为可能,这虽然不如每个测试理想,但足以满足我们的目的。
jsdom-with-timezone.js
const JSDOMEnvironment = require('jest-environment-jsdom');
/**
* Timezone-aware jsdom Jest environment. Supports `@timezone` JSDoc
* pragma within test suites to set timezone.
*
* You'd make another copy of this extending the Node environment,
* if needed for Node server environment-based tests.
*/
module.exports = class TimezoneAwareJSDOMEnvironment extends JSDOMEnvironment
{
constructor(config, context) {
// Allow test suites to change timezone, even if TZ is passed in a script.
// Falls back to existing TZ environment variable or UTC if no timezone is specified.
// IMPORTANT: This must happen before super(config) is called, otherwise
// it doesn't work.
process.env.TZ = context.docblockPragmas.timezone || process.env.TZ || 'UTC';
super(config);
}
};
tz-eastern.test.js
/**
* @timezone America/New_York
*/
describe('timezone: eastern', () => {
it('should be America/New_York timezone', () => {
expect(process.env.TZ).toBe('America/New_York');
expect(new Date().getTimezoneOffset()).toBe(300 /* 5 hours */);
});
});
jest.config.js
module.exports = {
"testEnvironment": "<rootDir>/jsdom-with-timezone.js"
}
将此方法与 jest.useFakeTimers('modern');
和 jest.setSystemTime()
结合使用足以进行更强大的日期测试,因此我想我会与其他人分享这种方法以从中受益!由于 pragma 处理是自定义的,因此您可以根据自己的用例以任何喜欢的方式对其进行自定义。
来源:
答案 3 :(得分:1)
直到最近,我使用以下内容来模拟处于不同的时区:
beforeEach(() => {
// Temporarily allow us to alter timezone calculation for testing
/*eslint no-extend-native: "off"*/
Date.prototype.getTimezoneOffset = jest.fn(() => 73);
});
afterEach(() => {
jest.resetAllMocks();
});
这并没有将测试代码放在特定的时区,而是确保任何时区偏移计算都正确进行。例如:
new Date("2010-10-01")
将比 new Date("2010-10-01T00:00:00")
早 73 分钟,前者相当于 new Date("2010-10-01T00:00:00Z")
(UTC 时区),后者在“本地时区”中
我说“直到最近”是因为最近对 date-fns 的更新似乎不再有效
答案 4 :(得分:0)
我遇到了同样的问题,我可以通过将process.env.TZ = 'your/timezone';
添加到我的jest.config.js
中来解决此问题。
也许这对您也有帮助:)
process.env.TZ = 'UTC';
module.exports = {
...
};