【问题标题】:jest typescript - Mock Date constructor开玩笑的打字稿 - 模拟日期构造函数
【发布时间】:2020-07-09 17:28:45
【问题描述】:

我正在尝试模拟 new Date() 以返回特定日期。以下代码:

const now = new Date()
jest.spyOn(global, 'Date').mockImplementation(() => now)

给出编译错误:Argument of type '() => Date' is not assignable to parameter of type '() => string'. Type 'Date' is not assignable to type 'string'

我认为原因是 jest 认为我试图模拟 Date() 而不是 new Date()。实际上,Date() 返回一个字符串。我该如何解决这个问题?

【问题讨论】:

  • 找到解决方案了吗?
  • 不。我使用了一种解决方法:我只在我的代码中使用new Date(Date.now()) 而从不使用new Date()。这样我就可以模拟Date.now()

标签: typescript unit-testing mocking jestjs spy


【解决方案1】:

一种解决方法是使用mockdate 库,可用于在“现在”时进行更改。

const MockDate = require('mockdate');

test('Mock Date to change when "now" is', () => {
  console.log('Normal:   ', new Date().getTime());

  MockDate.set(new Date(1466424490000));

  console.log('Mocked:   ', new Date().getTime());

  MockDate.reset();

  console.log('Restored: ', new Date().getTime());
});

而测试结果是这样的:

$ npm run test
> jest

 PASS  src/test.ts
  ✓ Mock Date to change when "now" is (8ms)

  console.log src/test.ts:4
    Normal:    1585505136315

  console.log src/test.ts:8
    Mocked:    1466424490000

  console.log src/test.ts:12
    Restored:  1585505136322

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        1.804s

the reference project on GitHub

【讨论】:

  • 谢谢。我认为该库之所以有效,是因为它使用的是 JS,而不是 TypeScript。我怀疑问题出在从 TS 到 JS 的翻译上。我正在寻找 TS 解决方案。
  • @EllaSharakanski 这个库现在在 TS 中。
【解决方案2】:

好吧,我试过这个解决方案,它奏效了..

class MockDate extends Date {
    constructor() {
        super("2020-05-14T11:01:58.135Z"); // add whatever date you'll expect to get
    }
}

在该测试的 beforeEach 中,我添加了:

// @ts-ignore
global.Date = MockDate;

这样,每当我调用一个内部有 new Date() 的函数时,它都会返回我在上面的 MockDate 类的构造函数中添加的日期!

【讨论】:

  • 你可以通过附加到你的类声明as unknown as typeof Date来避免//@ts-ignore
  • Jest 不建议这样做。您应该将 Jest Spies 用于任何全局类。
  • 好主意!但是当调用data.getFullYear() 我得到this is not a Date object.
【解决方案3】:

告诉编译器它想听什么:说它是一个转换为未知的字符串,然后是转换为字符串:

const now = new Date() as unknown as string

【讨论】:

  • 这对嘲笑没有帮助
  • 从 Aaron Goldman 的评论中你可以推断出他的意思是 const mockDate = new Date(1466424490000) const spy = jest.spyOn(global, 'Date') .mockImplementation(() => mockDate as unknown as string)
  • 但是 new Date() 现在返回一个字符串以及对 new Date() 的任何调用,例如new Date().getTime() 将不起作用,因为 "string".getTime() 不是函数
【解决方案4】:

Daryn 对 Arron 的回答的推理评论在没有额外包的情况下效果很好。

const mockDate = new Date();
jest.spyOn(global, "Date").mockImplementation(() => (mockDate as unknown) as string);
const myDate = new Date();

【讨论】:

  • 终于!这对我有用
【解决方案5】:

我在使用 jest typescript 模拟 new Date() 时遇到了同样的问题 当尝试在函数中模拟 Date 时:

export const checkValidTime(): boolean => { 
  const now = new Date();
  const maxAllowTime = new Date('2020-02-02 09:00:00');

  console.log(`currentTime: ${now.toLocaleString()}`);
  console.log(`maxAllowTime: ${maxAllowTime.toLocaleString()}`);

  return now > maxAllowTime;
}

单元测试中的模拟解决方案:

const mockDate = new Date('2021-09-03 08:00:10');
jest
    .spyOn(global, 'Date')
    .mockImplementationOnce(() => (mockDate as unknown) as string);
const valid = checkDateTime();
expect(valid).toEqual(true);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-02-06
    • 1970-01-01
    • 1970-01-01
    • 2020-01-07
    • 1970-01-01
    • 2018-05-03
    • 1970-01-01
    相关资源
    最近更新 更多