日期


¥Dates

模拟定时器 API 还允许模拟 Date 对象。对于测试与时间相关的功能或模拟内部日历功能(例如 Date.now())来说,这是一个有用的功能。

¥The mock timers API also allows the mocking of the Date object. This is a useful feature for testing time-dependent functionality, or to simulate internal calendar functions such as Date.now().

日期实现也是 MockTimers 类的一部分。请参阅它以获取方法和功能的完整列表。

¥The dates implementation is also part of the MockTimers class. Refer to it for a full list of methods and features.

注意:当一起模拟时,日期和定时器是依赖的。这意味着,如果你同时模拟了 DatesetTimeout,则提前时间也会提前模拟日期,因为它们模拟单个内部时钟。

¥Note: Dates and timers are dependent when mocked together. This means that if you have both the Date and setTimeout mocked, advancing the time will also advance the mocked date as they simulate a single internal clock.

下面的示例展示了如何模拟 Date 对象并获取当前 Date.now() 值。

¥The example below show how to mock the Date object and obtain the current Date.now() value.

import assert from 'node:assert';
import { test } from 'node:test';

test('mocks the Date object', (context) => {
  // Optionally choose what to mock
  context.mock.timers.enable({ apis: ['Date'] });
  // If not specified, the initial date will be based on 0 in the UNIX epoch
  assert.strictEqual(Date.now(), 0);

  // Advance in time will also advance the date
  context.mock.timers.tick(9999);
  assert.strictEqual(Date.now(), 9999);
});const assert = require('node:assert');
const { test } = require('node:test');

test('mocks the Date object', (context) => {
  // Optionally choose what to mock
  context.mock.timers.enable({ apis: ['Date'] });
  // If not specified, the initial date will be based on 0 in the UNIX epoch
  assert.strictEqual(Date.now(), 0);

  // Advance in time will also advance the date
  context.mock.timers.tick(9999);
  assert.strictEqual(Date.now(), 9999);
});

如果没有设置初始纪元,则初始日期将以 Unix 纪元中的 0 为基础。这是 1970 年 1 月 1 日 00:00:00 UTC。你可以通过将 now 属性传递给 .enable() 方法来设置初始日期。该值将用作模拟 Date 对象的初始日期。它可以是正整数,也可以是另一个 Date 对象。

¥If there is no initial epoch set, the initial date will be based on 0 in the Unix epoch. This is January 1st, 1970, 00:00:00 UTC. You can set an initial date by passing a now property to the .enable() method. This value will be used as the initial date for the mocked Date object. It can either be a positive integer, or another Date object.

import assert from 'node:assert';
import { test } from 'node:test';

test('mocks the Date object with initial time', (context) => {
  // Optionally choose what to mock
  context.mock.timers.enable({ apis: ['Date'], now: 100 });
  assert.strictEqual(Date.now(), 100);

  // Advance in time will also advance the date
  context.mock.timers.tick(200);
  assert.strictEqual(Date.now(), 300);
});const assert = require('node:assert');
const { test } = require('node:test');

test('mocks the Date object with initial time', (context) => {
  // Optionally choose what to mock
  context.mock.timers.enable({ apis: ['Date'], now: 100 });
  assert.strictEqual(Date.now(), 100);

  // Advance in time will also advance the date
  context.mock.timers.tick(200);
  assert.strictEqual(Date.now(), 300);
});

你可以使用 .setTime() 方法手动将模拟日期移动到另一个时间。此方法仅接受正整数。

¥You can use the .setTime() method to manually move the mocked date to another time. This method only accepts a positive integer.

注意:此方法将执行新时间过去的任何模拟定时器。

¥Note: This method will execute any mocked timers that are in the past from the new time.

在下面的示例中,我们为模拟日期设置新时间。

¥In the below example we are setting a new time for the mocked date.

import assert from 'node:assert';
import { test } from 'node:test';

test('sets the time of a date object', (context) => {
  // Optionally choose what to mock
  context.mock.timers.enable({ apis: ['Date'], now: 100 });
  assert.strictEqual(Date.now(), 100);

  // Advance in time will also advance the date
  context.mock.timers.setTime(1000);
  context.mock.timers.tick(200);
  assert.strictEqual(Date.now(), 1200);
});const assert = require('node:assert');
const { test } = require('node:test');

test('sets the time of a date object', (context) => {
  // Optionally choose what to mock
  context.mock.timers.enable({ apis: ['Date'], now: 100 });
  assert.strictEqual(Date.now(), 100);

  // Advance in time will also advance the date
  context.mock.timers.setTime(1000);
  context.mock.timers.tick(200);
  assert.strictEqual(Date.now(), 1200);
});

如果你有任何设置为过去运行的定时器,它将像调用 .tick() 方法一样执行。如果你想测试已经过去的时间相关功能,这非常有用。

¥If you have any timer that's set to run in the past, it will be executed as if the .tick() method has been called. This is useful if you want to test time-dependent functionality that's already in the past.

import assert from 'node:assert';
import { test } from 'node:test';

test('runs timers as setTime passes ticks', (context) => {
  // Optionally choose what to mock
  context.mock.timers.enable({ apis: ['setTimeout', 'Date'] });
  const fn = context.mock.fn();
  setTimeout(fn, 1000);

  context.mock.timers.setTime(800);
  // Timer is not executed as the time is not yet reached
  assert.strictEqual(fn.mock.callCount(), 0);
  assert.strictEqual(Date.now(), 800);

  context.mock.timers.setTime(1200);
  // Timer is executed as the time is now reached
  assert.strictEqual(fn.mock.callCount(), 1);
  assert.strictEqual(Date.now(), 1200);
});const assert = require('node:assert');
const { test } = require('node:test');

test('runs timers as setTime passes ticks', (context) => {
  // Optionally choose what to mock
  context.mock.timers.enable({ apis: ['setTimeout', 'Date'] });
  const fn = context.mock.fn();
  setTimeout(fn, 1000);

  context.mock.timers.setTime(800);
  // Timer is not executed as the time is not yet reached
  assert.strictEqual(fn.mock.callCount(), 0);
  assert.strictEqual(Date.now(), 800);

  context.mock.timers.setTime(1200);
  // Timer is executed as the time is now reached
  assert.strictEqual(fn.mock.callCount(), 1);
  assert.strictEqual(Date.now(), 1200);
});

使用 .runAll() 将执行当前队列中的所有定时器。这还将模拟日期提前到最后执行的定时器的时间,就好像时间已经过去一样。

¥Using .runAll() will execute all timers that are currently in the queue. This will also advance the mocked date to the time of the last timer that was executed as if the time has passed.

import assert from 'node:assert';
import { test } from 'node:test';

test('runs timers as setTime passes ticks', (context) => {
  // Optionally choose what to mock
  context.mock.timers.enable({ apis: ['setTimeout', 'Date'] });
  const fn = context.mock.fn();
  setTimeout(fn, 1000);
  setTimeout(fn, 2000);
  setTimeout(fn, 3000);

  context.mock.timers.runAll();
  // All timers are executed as the time is now reached
  assert.strictEqual(fn.mock.callCount(), 3);
  assert.strictEqual(Date.now(), 3000);
});const assert = require('node:assert');
const { test } = require('node:test');

test('runs timers as setTime passes ticks', (context) => {
  // Optionally choose what to mock
  context.mock.timers.enable({ apis: ['setTimeout', 'Date'] });
  const fn = context.mock.fn();
  setTimeout(fn, 1000);
  setTimeout(fn, 2000);
  setTimeout(fn, 3000);

  context.mock.timers.runAll();
  // All timers are executed as the time is now reached
  assert.strictEqual(fn.mock.callCount(), 3);
  assert.strictEqual(Date.now(), 3000);
});