Set*_*amp 18 javascript jestjs
我有一个方法,它依赖于new Date创建一个日期对象,然后操纵它.我正在测试操作是否按预期工作,因此我需要将返回的日期与预期日期进行比较.为了做到这一点,我需要确保new Date在测试和被测试的方法中返回相同的值.我怎样才能做到这一点?
有没有办法实际模拟构造函数的返回值?
我可以使用提供日期对象的函数创建一个模块,并且可以进行模拟.但这似乎是我代码中不必要的抽象.
一个要测试的示例函数......
module.exports = {
sameTimeTomorrow: function(){
var dt = new Date();
dt.setDate(dt + 1);
return dt;
}
};
Run Code Online (Sandbox Code Playgroud)
我该如何模拟返回值new Date()?
Yuc*_*uci 78
更新:此答案是jest < version 26查看最近玩笑版本的此答案的方法。
您可以使用jest.spyOn如下方法模拟像 new Date() 这样的构造函数:
test('mocks a constructor like new Date()', () => {
console.log('Normal: ', new Date().getTime())
const mockDate = new Date(1466424490000)
const spy = jest
.spyOn(global, 'Date')
.mockImplementation(() => mockDate)
console.log('Mocked: ', new Date().getTime())
spy.mockRestore()
console.log('Restored: ', new Date().getTime())
})
Run Code Online (Sandbox Code Playgroud)
输出如下所示:
Normal: 1566424897579
Mocked: 1466424490000
Restored: 1566424897608
Run Code Online (Sandbox Code Playgroud)
请参阅GitHub 上的参考项目。
注意:如果您使用的是 TypeScript 并且会遇到编译错误,Argument of type '() => Date' is not assignable to parameter of type '() => string'. Type 'Date' is not assignable to type 'string'. 在这种情况下,解决方法是使用mockdate库,该库可用于更改“现在”的时间。有关更多详细信息,请参阅此问题。
Thd*_*hdK 47
从 jest 26 开始,您可以使用支持该方法的“现代”fakeTimers 实现(请参阅此处的文章)jest.setSystemTime。
beforeAll(() => {
jest.useFakeTimers('modern');
jest.setSystemTime(new Date(2020, 3, 1));
});
afterAll(() => {
jest.useRealTimers();
});
Run Code Online (Sandbox Code Playgroud)
请注意,这'modern'将是 jest 版本 27 的默认实现。
请参阅setSystemTime 此处的文档。
小智 10
尽管其他答案解决了问题,但我发现它更自然,并且通常适用于仅模拟 Date 的“无参数构造函数”行为,同时保持 Date 的其他功能完好无损。例如,当 ISO 日期字符串传递给构造函数时,期望返回此特定日期而不是模拟日期可能是合理的。
test('spies new Date(...params) constructor returning a mock when no args are passed but delegating to real constructor otherwise', () => {
const DateReal = global.Date;
const mockDate = new Date("2020-11-01T00:00:00.000Z");
const spy = jest
.spyOn(global, 'Date')
.mockImplementation((...args) => {
if (args.length) {
return new DateReal(...args);
}
return mockDate;
})
const dateNow = new Date();
//no parameter => mocked current Date returned
console.log(dateNow.toISOString()); //outputs: "2020-11-01T00:00:00.000Z"
//explicit parameters passed => delegated to the real constructor
console.log(new Date("2020-11-30").toISOString()); //outputs: "2020-11-30T00:00:00.000Z"
//(the mocked) current Date + 1 month => delegated to the real constructor
let dateOneMonthFromNow = new Date(dateNow);
dateOneMonthFromNow.setMonth(dateNow.getMonth() + 1);
console.log(dateOneMonthFromNow.toISOString()); //outputs: "2020-12-01T00:00:00.000Z"
spy.mockRestore();
});
Run Code Online (Sandbox Code Playgroud)
您可以使用茉莉花的spyOn(jest是在茉莉花上构建的)来模拟Date的getDate原型,如下所示:
spyOn(Date.prototype, 'setDate').and.returnValue(DATE_TO_TEST_WITH);
Run Code Online (Sandbox Code Playgroud)
SpyOn自身完成后也将清除,并且仅在测试范围内持续。
小智 7
您可以使用模拟函数覆盖Date构造函数,该函数返回具有指定日期值的构造好的Date对象:
var yourModule = require('./yourModule')
test('Mock Date', () => {
const mockedDate = new Date(2017, 11, 10)
const originalDate = Date
global.Date = jest.fn(() => mockedDate)
global.Date.setDate = originalDate.setDate
expect(yourModule.sameTimeTomorrow().getDate()).toEqual(11)
})
Run Code Online (Sandbox Code Playgroud)
您可以在此处测试示例:https : //repl.it/@miluoshi5/jest-mock-date
| 归档时间: |
|
| 查看次数: |
16920 次 |
| 最近记录: |