Jest: 模拟日期的当前时间

创建于 2016-12-06  ·  72评论  ·  资料来源: facebook/jest

@SimenB 25-05-2020 编辑:查看更新的答案: https :

有没有办法模拟当前日期? 那么new Date()Date.now()返回一个模拟时间而不是当前时间?

最有用的评论

对于遇到此错误的其他任何人,我遇到了一些问题,因为全局 Date 对象具有构造函数以外的属性。 我做了以下事情:

const DATE_TO_USE = new Date('2016');
const _Date = Date;
global.Date = jest.fn(() => DATE_TO_USE);
global.Date.UTC = _Date.UTC;
global.Date.parse = _Date.parse;
global.Date.now = _Date.now;

所有72条评论

Date.now = jest.fnglobal.Date = jest.fn()

对于遇到此错误的其他任何人,我遇到了一些问题,因为全局 Date 对象具有构造函数以外的属性。 我做了以下事情:

const DATE_TO_USE = new Date('2016');
const _Date = Date;
global.Date = jest.fn(() => DATE_TO_USE);
global.Date.UTC = _Date.UTC;
global.Date.parse = _Date.parse;
global.Date.now = _Date.now;

如果您不需要断言构造函数是如何被调用的,那么扩展就足够了:

const constantDate = new Date('2017-06-13T04:41:20')

/*eslint no-global-assign:off*/
Date = class extends Date {
  constructor() {
    return constantDate
  }
}

这对于Date.now()

const now = Date.now()
Date.now = jest.genMockFunction().mockReturnValue(now)

每当您模拟约会时,请不要忘记放回真实版本。
@callemo评论之后,您可以使用以下代码段:

describe('getTimestamp', () => {
  const RealDate = Date

  function mockDate (isoDate) {
    global.Date = class extends RealDate {
      constructor () {
        return new RealDate(isoDate)
      }
    }
  }

  afterEach(() => {
    global.Date = RealDate
  })

  it('should return timestamp', () => {
    mockDate('2017-11-25T12:34:56z')
    expect(getTimestamp()).toEqual('20171125123456')
  })
})

可以说,在运行jest.runTimersToTime()和其他时间模拟函数时,Date 也应该向前移动。 我被同样的问题所困扰,因为我的部分代码取决于时间,部分取决于超时。 同时模拟它们——即运行模拟定时器并切换Date.nowPerformance.now模拟并不是最好的体验。

“统一”计时器模拟的解决方案是使用lolex而不是jest内置函数,如下所示:

import lolex from 'lolex'

describe('tests', () => {
  let clock
  beforeEach(() => {clock = lolex.install()})
  afterEach(() => {clock = clock.uninstall()})

  test('garbage collects after keep alive', () => {
    // ...
    clock.tick(500)
    // ...
  })
})

但是内置此功能会很棒。

老问题,但mockdate使这很容易: https :

https://jasmine.github.io/2.2/introduction?spec=jasmine.any#section -Mocking_the_Date

   describe("Mocking the Date object", function(){
     it("mocks the Date object and sets it to a given time", function() {
       var baseTime = new Date(2013, 9, 23);
       jasmine.clock().mockDate(baseTime);
       jasmine.clock().tick(50);
       expect(new Date().getTime()).toEqual(baseTime.getTime() + 50);
     });
   });

@drpicox这是一个不错的解决方案,但是 AFAIK 它不会模拟performance.now() ,这是一个有用的、只向前的时钟(即不会被用户更改其系统的 DateTime 设置后退)。

事实上,它在 Jest 中不起作用。 Jest 使用 Jasmine v1.5.2-lite,所以它没有时钟。 我正在使用lolex

Date.now()对大多数应用来说已经足够了, permofrmance.now()它还没有出现在 node 中——例如不能在 SSR 中使用——所以它似乎没什么大不了的。

当然,lolex 并没有和 jest 融为一体。

@drpicox啊,很高兴知道它不起作用。
performance.now()存在于节点中,我相信从 v8.5.0 开始。 您可以从内置模块'perf_hooks'导入performance 'perf_hooks'

尽管如此,考虑到目前的情况和获得的投票/评论数量,我想 ping @cpojer以考虑重新打开这个问题。

FWIW 我很想集成 lolex - 这是我使用的唯一一个我认为 Jest 缺少电池的库

@cpojer无论如何我们都可以重新打开它。 截至目前,还没有真正嘲笑日期模拟的时间通过一个简单的方法的一种方式。

jasmine 有一个时钟类,您可以通过以下方式模拟日期提前时间:

jasmine.clock().install(); //in a beforeEach
jasmine.clock().uninstall(); // in a AfterEach
jasmine.clock().mockDate(new Date('1984/12/15'));

// and very important... the pass of time!
jasmine.clock().tick(100);

很想拥有类似的本地功能。 https://github.com/jasmine/jasmine/blob/master/src/core/Clock.js

我们将尝试迁移到支持您的用例的 Lolex。 见#5165

如果您需要模拟测试环境的 Date _outside_。 我需要为显示日期的 UI 拍摄可预测的图像快照。

这对我有用:
https://github.com/schickling/timemachine

timemachine.config({
  dateString: 'December 25, 1991 13:12:59'
});
console.log(new Date()); // December 25, 1991 13:12:59

@omegdadisc的建议是我认为最好的。 Mocking Date 总是返回相同的日期(正如第一个答案中所建议的那样)会弄乱new Date(2018, 2, 3)所以对我来说不是一个有效的选择。

请注意,您还需要精确时区以使其在任何地方都能正常工作,例如在 Travis 上并产生相同的结果。

timemachine.config({
  dateString: 'December 25, 1991 13:12:59 GMT'
});

以下测试存根 Date 在测试生命周期中返回一个常量。

let timeNow;
const realDate = Date;

describe("Stubbed Date", () => {
  beforeAll(() => {
    timeNow = Date.now();
    const _GLOBAL: any = global;
    _GLOBAL.Date = class {
      public static now() {
        return timeNow;
      }

      constructor() {
        return timeNow;
      }

      public valueOf() {
        return timeNow;
      }
    };
  });

  afterAll(() => {
    global.Date = realDate;
  });

  it("provides constant timestamps", () => {
    const ts1 = Date.now();
    const ts2 = +new Date();
    expect(ts1).toEqual(ts2);
    expect(ts2).toEqual(timeNow);
  });
});

_GLOBAL只是一个满足打字稿的代理变量。

我需要模拟Date.now()

在配置中或在测试对我有用之前设置以下行:

jest.spyOn(Date, 'now').mockImplementation(() => 1479427200000)

我喜欢@vcarel的方法,但在我的情况下, Date 构造函数在某些情况下与参数一起使用,所以我需要修改它以接受其他日期。 我还添加了 Date.now()

describe('getTimestamp', () => {
  const RealDate = Date

  function mockDate (isoDate) {
    global.Date = class extends RealDate {
      constructor(...theArgs) {
        if (theArgs.length) {
          return new RealDate(...theArgs);
        }
        return new RealDate(isoDate);
      }

      static now() {
        return new RealDate(isoDate).getTime();
      }
    }
  }

  afterEach(() => {
    global.Date = RealDate
  })

  it('should return timestamp', () => {
    mockDate('2017-11-25T12:34:56z')
    expect(getTimestamp()).toEqual('20171125123456')
  })
})

我正在使用这个,我很满意: https :

我已经这样做了

~~~
描述('测试',()=> {
const constantDate = new Date('2018-01-01T12:00:00')

beforeAll(() => {
global.Date = 类扩展日期 {
构造函数(){
极好的()
返回常量日期
}
}
})
~~~

就像对@callemo@iwarner的回答

做这样的事情可能不太容易出错,因为它每次都返回一个新的日期实例:

  const constantDate = new Date('2018-01-01T12:00:00')

  beforeAll(() => {
    global.Date = class extends Date {
      constructor () {
        super(constantDate.getTime())
      }
    }
  })

这允许在不改变 constantDate 的情况下使用改变日期对象(例如 setMinutes)的函数,从而改变从新日期返回的日期,例如

describe('Test', () => {
  const constantDate = new Date('2018-01-01T12:00:00')

  beforeAll(() => {
    global.Date = class extends Date {
      constructor () {
        super()
        return constantDate
      }
    }
  });

  it('it should not be possible to mutate the  original date but it is.', () => {
    const date1 = new Date();
    date1.setMinutes(5);
    const date2 = new Date();
    console.log(date2.getMinutes()); // Will print 5
  });
});

这是我在阅读以上所有内容后使用的:

let currentDate;

beforeAll(() => {
  currentDate = new Date();

  const RealDate = Date;
  global.Date = jest.fn(() => new RealDate(currentDate.toISOString()));
  Object.assign(Date, RealDate);
});

@samboylett这是否会afterAll函数中重置它?

它不会影响不同文件中的测试。 对我来说,当前文件中的所有内容都需要模拟日期,但是如果您需要在同一文件中的测试之间重置它,则应该使用 beforeEach 和 afterEach,然后将其重新设置回 afterEach:

afterEach(() => {
  global.Date = RealDate;
});

@samboylett谢谢! 我设法通过使用您的示例作为基础来进行日期测试。

const myDate = new Date(2018, 6, 11);

const RealDate = Date;

describe('testcase', () => {
  beforeEach(() => {
    global.Date = jest.fn(
      (...props) =>
        props.length
          ? new RealDate(...props)
          : new RealDate(myDate)
    );
    Object.assign(Date, RealDate);
  });

  afterEach(() => {
    global.Date = RealDate;
  });
});

也许你需要jest-date-mock

为您提供简单的 API 来控制测试用例的当前时间戳。

import { advanceBy, advanceTo, clear } from 'jest-date-mock';

test('usage', () => {
  advanceTo(new Date(2018, 5, 27, 0, 0, 0)); // reset to date time.

  const now = Date.now();

  advanceBy(3000); // advance time 3 seconds
  expect(+new Date() - now).toBe(3000);

  advanceBy(-1000); // advance time -1 second
  expect(+new Date() - now).toBe(2000);

  clear();
  Date.now(); // will got current timestamp
});

上述解决方案没有涵盖我的用例。 我基于@callemo做了以下

export function mockDate({year = 2017, month = 9, day = 16}) {
    const globalDate = global.Date
    global.Date = class MockDate extends Date {
        constructor() {
            super()
            this.setFullYear(year)
            this.setMonth(month)
            this.setDate(day)
        }
    }
    global.Date.mockRestore = () => global.Date = globalDate
}

@javadoug你的情况是什么?

@javadoug你的情况是什么?

@hustcc mockDate() instanceof Date === true

支持@javadoug新版本jest-date-mockhttps://github.com/hustcc/jest-date-mock/pull/7

“我并不总是嘲笑时间,但当我这样做时,它是在开玩笑”——臭名昭著的@satub

我需要模拟new Date()但需要其余的Date功能正常工作。 这是对我有用的解决方案。

describe('...', () => {
  const RealDate = Date;

  function mockDate(isoDate) {
    global.Date = class extends RealDate {
      constructor(...args) {
        if (args.length) return new RealDate(...args);
        return new RealDate(isoDate);
      }
    };
  }

  afterEach(() => {
    global.Date = RealDate;
  });

  it('...', () => {
    mockDate('2018-01-01');
    // rest of the code
  });
})

每当我尝试分配给 global.Date 时,我都会收到错误消息:

Error: Error: ReferenceError: Date is not defined
    at Object.<anonymous>.exportObject.JUnitXmlReporter.self.specDone (/src/node_modules/jasmine-reporters/src/junit_reporter.js:274:33)
    at dispatch (/src/node_modules/jest-jasmine2/build/jasmine/report_dispatcher.js:70:26)
    at ReportDispatcher.specDone (/src/node_modules/jest-jasmine2/build/jasmine/report_dispatcher.js:62:247)
    at Object.specResultCallback (/src/node_modules/jest-jasmine2/build/jasmine/Env.js:411:18)
    at Spec.attr.resultCallback (/src/node_modules/jest-jasmine2/build/setup_jest_globals.js:67:24)
    at complete (/src/node_modules/jest-jasmine2/build/jasmine/Spec.js:111:10)
    at currentRun.then (/src/node_modules/jest-jasmine2/build/jasmine/Spec.js:107:30)

看起来问题是我正在使用在测试上下文中执行的 JUnit 报告器,并且使用的 Date 已经被销毁,因为匿名类被销毁。

所以是的,当您使用上述所有建议时,全局日期会搞砸。 只有当你使用非标准的记者时才会出现问题。

记者不应该在沙箱内被处决。 不过,Jasmine 记者可能会使用一些并非有意支持的 jasmime 内容

哦,所以你是说不支持这种代码?

const jasmine = global.jasmine;
jasmine.getEnv().addReporter(junitReporter)

错误发生在这里:
https://github.com/facebook/jest/blob/f9fd98fd4e38978e96a86f1c8796593cad7ac470/packages/jest-jasmine2/src/jasmine/ReportDispatcher.js#L63 -L72

正确,你应该使用
https://jestjs.io/docs/en/configuration#reporters -array-modulename-modulename-options。
例如https://github.com/jest-community/jest-junit

@niieani

“统一”计时器模拟的解决方案是使用lolex而不是jest内置函数,如下所示:

我尝试了这个例子,结果导致我的测试永远挂起(在使用 [email protected] 的 CRA 中)。 有人在 Jest 上使用 lolex 取得成功吗?

@kentcdodds确保不要同时使用开玩笑的假计时器。 如果它仍然挂起,介意创建一个复制问题吗? Lolex 绝对应该工作

是的,它在孤立的情况下对我来说很好用,所以我可能会在其他地方做一些奇怪的事情。 谢谢!

如果您只需要模拟这些情况:

new Date()
new Date('2018-09-20T23:00:00Z') 
const currentDate = new Date('2018-09-20T23:00:00Z');
Date = class extends Date {
  constructor(date) {
    if (date) {
        return super(date);
    }

    return currentDate;
  }
}

这是我在阅读以上所有内容后使用的:

let currentDate;

beforeAll(() => {
  currentDate = new Date();

  const RealDate = Date;
  global.Date = jest.fn(() => new RealDate(currentDate.toISOString()));
  Object.assign(Date, RealDate);
});

谢谢@samboylett

这在模拟 new Date() 时对我有用

@petromoldovan绝对是最好的答案。

在测试结束时添加对mockRestore的调用以恢复原始日期:

const dateNowMockFn = jest.spyOn(Date, 'now').mockImplementation(() => 1479427200000);
// ... code with tests
dateNowMockFn.mockRestore();

稍微改进了@vcarel解决方案,以防您希望模拟返回 Date 实例而不是新类之一:

    const RealDate = Date

    const mockDate = (isoDate) => {
      global.Date = class extends RealDate {
        constructor () {
          return super(isoDate)
        }
      }
    }

    afterEach(() => {
      global.Date = RealDate
    })

我可能在这里对风车倾斜,但值得指出一句古老的格言:不要嘲笑你没有的东西。 相反,将它包装在一个函数中。 现在使用默认参数值非常方便:

const myFunc = (msg, date = new Date()) => console.log(`${msg}! ${date}`);

现在在生产代码中,您可以利用默认值:

myFunc("Hello"); // => Hello! Fri Mar 22 2019 21:11:26 GMT-0400 (EDT)

在测试代​​码中,您可以显式传入日期,从而模拟它:

myFunc("Hello", dateObj) // => Hello! ...

@yawaramin对此肯定有一些不同的观点。 有一个阵营认为测试应该为应用程序代码服务,并且有一点过去了,尾巴开始摇摆不定(Pete Hunt 对此有一些强烈的看法

并不是说您建议的方法不是一个有效的选择,而是说它也许可以作为一种适合情况的方法来呈现

@cheapsteak我认为情境适当是事物的默认状态。 温和地提醒人们总是有机会提高可测试性并且这样做通常会提高可维护性并没有什么坏处:-)

有没有办法在调度计时器时获取 jest 的当前时间? 像 jest.now 之类的东西?

假设我有计时器和对 Date.now() 的调用。 我调用 jest.runAllTimers()。 如果我可以调用 jest.spyOn(Date, 'now').mockImplementation(() => something ) 以便计时器回调运行并可以检查模拟时间,那就太酷了。

我需要模拟Date.now()

在配置中或在测试对我有用之前设置以下行:

jest.spyOn(Date, 'now').mockImplementation(() => 1479427200000)

有趣的是它如何适用于这么多人但不适用于我。 唔。

我不知道发生了什么,但无论我如何重新分配DateDate.now()始终存在并始终返回有效值。

Date.now = null什么都不做。
global.Date.now = null什么都不做。
jest.spyOn(Date, 'now').mockImplementation(() => 1479427200000);什么都不做。
安装和使用lolex对超时有效,但对Date.now()无效
MockDate无效。

我想我错过了一些明显的东西。 也许另一个依赖正在做某事......太困惑了。

@mherodev检查您的测试,您是否在测试函数执行/组件渲染之前模拟日期?

在测试块内,我正在做类似的事情......

      Date.now = () => 1;
      Date = null;
      global.Date = null;
      console.log(`Date.now()`, Date.now()); // Date.now() 1560239936091

但是这种覆盖没有任何作用。 我觉得很混乱。

我跟着Hugo 的教程,最后做了:

  // @ts-ignore
  .spyOn(global.Date, 'constructor')
  .mockImplementationOnce(() => new Date('2019-06-19T00:07:19.309Z'))

因此, new Date()将始终返回new Date('2019-06-19T00:07:19.309Z')

更新:由于 babel 在我的环境中转换方式的错误,我的 Date 模拟似乎无法正常工作。 与我们如何使用@babel/runtime-corejs2

终极解决方案: jest-date-mock

  • 安装

在 jest 下的 package.json 中,创建一个 setupFiles 数组并将 jest-date-mock 添加到该数组中。

{
  "jest": {
    "setupFiles": ["./__setups__/other.js", "jest-date-mock"]
  }
}
  • 用法

为您提供简单的 API 来控制测试用例的当前时间戳。

import { advanceBy, advanceTo, clear } from 'jest-date-mock';

test('usage', () => {
  advanceTo(new Date(2018, 5, 27, 0, 0, 0)); // reset to date time.

  const now = Date.now();

  advanceBy(3000); // advance time 3 seconds
  expect(+new Date() - now).toBe(3000);

  advanceBy(-1000); // advance time -1 second
  expect(+new Date() - now).toBe(2000);

  clear();
  Date.now(); // will got current timestamp
});

我认为:所有其他解决方案都不是系统的,或暂时的。

看起来 babel 转换打破了以前的解决方法。

我的解决方案是添加一个名为setupMockDate.js的新文件

const mockDate = DateClass => {
  function Mock(...args) {
    return args.length === 0
      ? new DateClass(Mock.now())
      : new DateClass(...args)
  }
  Object.setPrototypeOf(Mock, DateClass)
  Mock.prototype = DateClass.prototype
  let now
  Mock.now = () => now === undefined ? DateClass.now() : now
  Mock.mockNow = value => now = value
  Mock.mockRestore = () => Mock.mockNow()
  return Mock
}
global.Date = mockDate(Date)

jest.config.js setupFilesAfterEnv条目的setupFiles ),添加'<rootDir>/jest/setupMockDate.js'

现在,您可以运行

Date.mockNow(10)
expect(Date.now()).toBe(10)
Date.mockRestore()
expect(Date.now()).not.toBe(10)

聚会迟到了,但我认为 jest 具有您需要的所有功能。

describe('how to mock date.now()', function() {
  beforeEach(() => {
    this.timestamp = 0
    global.Date.now = jest.fn().mockImplementation(() => this.timestamp)
  })

  afterEach(() => {
    jest.clearAllMocks()
  })

  it('can advance in time', () => {
    const then = Date.now()

    this.timestamp += 1000

    const now = Date.now()

    expect(now - then).toBe(1000)
  })

我正在使用 vue-moment 和 jest,并且发现最好的方法是做这样的事情:

import { mount, createLocalVue } from '@vue/test-utils';
import TripList from 'components/trip-list.vue';

const localVue = createLocalVue();
localVue.use(require('vue-moment'));

describe('TripList', () => {

it('text shows current date', () => {
    const myDate = new Date(2019, 5, 5);

    const wrapper = mount(TripList, {
      localVue,
    });

    wrapper.vm.$moment.now = () => myDate;
    wrapper.vm.$forceUpdate();

    expect(wrapper.html()).toContain('Thu, Oct 3rd');
  });
})

使用 ES6

const fixedDate = new Date('2019-03-1');
const RealDate = Date;

beforeEach(() => { Date.now = () => fixedDate; });
afterEach(() => { global.Date = RealDate; });

如果您使用Date.now()

const dateSpy = jest.spyOn(Date, 'now');
dateSpy.mockReturnValue(TIMESTAMP);

对于遇到此错误的其他任何人,我遇到了一些问题,因为全局 Date 对象具有构造函数以外的属性。 我做了以下事情:

const DATE_TO_USE = new Date('2016');
const _Date = Date;
global.Date = jest.fn(() => DATE_TO_USE);
global.Date.UTC = _Date.UTC;
global.Date.parse = _Date.parse;
global.Date.now = _Date.now;

我想模拟整个 Date 类, @kristojorg建议的方法似乎很理想。

我不确定这是否是合适的方法,但是通过修复@nilobarp提到的打字问题,该解决方案在 TypeScript 中运行良好:

describe('Mock Date', () => {
  const realDateNow = Date.bind(global.Date);

  beforeAll(() => {
    // Fix the time to 2020-1-1 1hr:1min:1sec in order to match
    // snapshots for the DownloadConfirmDialog component.
    const fixedDate = new Date(2020, 0, 1, 1, 1, 1);
    const d = Date;

    // This will only mock any Date objects instantiated with new 
    // and not Date.now().
    const _global: NodeJS.Global = global;
    _global.Date = jest.fn(() => fixedDate);
    _global.Date.parse = d.parse;
    _global.Date.UTC = d.UTC;
    _global.Date.now = d.now;
  });

  it('shows mocked date', () => {
    // Shows 2020-01-01T01:01:01.000Z as the current Date
    // for an instantiated Date object.
    console.log(new Date().toISOString());
  });

  afterAll(() => {
    // Reverts to the current Date object.
    global.Date = realDateNow;
    console.log(new Date().toISOString());
  });
});

值得一提的是,这只适用于您实例化一个新的Date对象,而不适用于Date.now() 。 有关于 Date.now

在测试块内,我正在做类似的事情......

      Date.now = () => 1;
      Date = null;
      global.Date = null;
      console.log(`Date.now()`, Date.now()); // Date.now() 1560239936091

但是这种覆盖没有任何作用。 我觉得很混乱。

我遇到了同样的问题:测试了在这个问题中找到的一大堆代码示例,但没有一个对我有用:模拟似乎被忽略了。

你是如何解决你的问题的?

我们也在使用 Babel,所以这也可能相关。

在测试块内,我正在做类似的事情......

      Date.now = () => 1;
      Date = null;
      global.Date = null;
      console.log(`Date.now()`, Date.now()); // Date.now() 1560239936091

但是这种覆盖没有任何作用。 我觉得很混乱。

我遇到了同样的问题:测试了在这个问题中找到的一大堆代码示例,但没有一个对我有用:模拟似乎被忽略了。

你是如何解决你的问题的?

我们也在使用 Babel,所以这也可能相关。

@warpdesign这个解决方案似乎适用于我在 TypeScript 中使用 Jest。

describe('Mock Date.now', () => {
  // Bind to the original Date so we can set it back after all tests are finished.
  const realDateNow = Date.now.bind(global.Date);

  beforeAll(() => {
    // Return 1 millisecond when calling Date.now() in tests.
    const dateNowStub = jest.fn(() => 1);
    global.Date.now = dateNowStub;
  });

  it('shows mocked date', () => {
    console.log(Date.now());  // Returns 1.
  });

  afterAll(() => {
    // Set back to the original Date object.
    global.Date.now = realDateNow;
    console.log(Date.now()); // Returns current time in milliseconds.
  });
});

来自这篇关于在 Jest 中模拟当前日期的文章。

终极解决方案: jest-date-mock

  • 安装

在 jest 下的 package.json 中,创建一个 setupFiles 数组并将 jest-date-mock 添加到该数组中。

{
  "jest": {
    "setupFiles": ["./__setups__/other.js", "jest-date-mock"]
  }
}
  • 用法

为您提供简单的 API 来控制测试用例的当前时间戳。

import { advanceBy, advanceTo, clear } from 'jest-date-mock';

test('usage', () => {
  advanceTo(new Date(2018, 5, 27, 0, 0, 0)); // reset to date time.

  const now = Date.now();

  advanceBy(3000); // advance time 3 seconds
  expect(+new Date() - now).toBe(3000);

  advanceBy(-1000); // advance time -1 second
  expect(+new Date() - now).toBe(2000);

  clear();
  Date.now(); // will got current timestamp
});

我认为:所有其他解决方案都不是系统的,或暂时的。

谢谢你成功了!!

我跟着Hugo 的教程,最后做了:

  // @ts-ignore
  .spyOn(global.Date, 'constructor')
  .mockImplementationOnce(() => new Date('2019-06-19T00:07:19.309Z'))

因此, new Date()将始终返回new Date('2019-06-19T00:07:19.309Z')

这人是什么鬼。 你说 Hugo 的教程,而 Hugo 说的是你的……请不要误导我们。

Jest 26 支持使用现代假定时器模拟Datehttps: //jestjs.io/blog/2020/05/05/jest-26#new -fake-timers

如果您一直在尝试模拟 TS 中的 Date 构造函数,请尝试以下操作:

const mockDate = new Date('Tue, 23 Jun 2020 14:34:56');
const RealDate = Date;
(global as any).Date = class extends RealDate {
  constructor() {
    super();
    return mockDate;
  }
};

// test some date related functionality

global.Date = RealDate;

Jest 26 支持使用现代假定时器模拟Datehttps: //jestjs.io/blog/2020/05/05/jest-26#new -fake-timers

@SimenB太好了,我刚刚更新到 v26,但不知道我们如何使用 jest 来模拟日期。 jest 文档只讨论如何模拟计时器,以便您可以测试 setTimeOut,但是您如何模拟“new Date()”?

@gregveres这是一个示例测试套件,它将系统时间( Date方法)设置为固定日期并处理该时间的提前。

const FIXED_SYSTEM_TIME = '2020-11-18T00:00:00Z';

describe('Set Fixed Date', () => {
    beforeEach(() => {
        jest.useFakeTimers('modern');
        jest.setSystemTime(Date.parse(FIXED_SYSTEM_TIME));
    });

    afterEach(() => {
        jest.useRealTimers();
    });

    it('Should reflect fixed date', () => {
        expect(new Date().toISOString()).toEqual(FIXED_SYSTEM_TIME);

        const MS_TO_ADVANCE = 5000;

        jest.advanceTimersByTime(MS_TO_ADVANCE);

        expect(new Date().toISOString()).toEqual(new Date(Date.parse(FIXED_SYSTEM_TIME) + MS_TO_ADVANCE).toISOString());
    });
});

_更新:根据@alexdanilowi​​cz在下面的评论包含afterEach()

2020 年 11 月更新

_Bolding ^ 因为这个帖子越来越老并且链接到一个流行的 stackoverflow 帖子_

@seansullivan 太棒了! 仅供参考,如果我错了,请纠正我,但我认为在您的规格中添加 afterEach(或 afterAll)以将日期重置为现实会很好。 只是为了安全。

describe('Test', () => {
  // to avoid race conditions between expected and actual date values
  beforeAll(() => {
    jest.useFakeTimers('modern'); // tell Jest to use a different timer implementation.
    jest.setSystemTime(new Date('20 Aug 2020 00:12:00 GMT').getTime())
  });

  afterAll(() => {
    // Back to reality...
    jest.useRealTimers();
  });

@alexdanilowi​​cz完美。 是的,我忽略了在我的示例中包含清理。 我将更新afterEach()以确保任何找到此线程的人都保持理智。 谢谢!

此页面是否有帮助?
0 / 5 - 0 等级