模拟 DayJs 默认函数及其链式方法

5

我想模拟 dayjs() 默认函数,并使用特定日期和时间进行模拟,还希望模拟其嵌套方法,即 .utc() 和 .add()

目前为止,这是我尝试过的:

abc.ts:

getEarliestDate() {
    const {
        minHour,
        maxHour
    } = operatingHours;
    const earliestDateTime = dayjs().add(sla + 1, 'minute');
    const earliestDateTimeUTC = earliestDateTime.utc();

    return dayjs().add(121, 'minute').format('YYYY-MM-DD HH:mm');
}

abc.test.ts:

import { abc } from '../../src/common/serviceFactory';
import dayjs from 'dayjs';

jest.mock('dayjs', () =>
  jest.fn((...args) => jest.requireActual('dayjs')(args.filter((arg) => arg).length > 0 ? args : '2020-08-12')),
);

jest.mock('dayjs', () => ({
  default: jest.requireActual('dayjs')(`2020-08-18 12:00:00`),
  extend: jest.fn(),
  utc: jest.fn((...args) => {
    const dayjs = jest.requireActual('dayjs');
    dayjs.extend(jest.requireActual('dayjs/plugin/utc'));

    return dayjs.utc(args.filter((arg) => arg).length > 0 ? args : '12:00:00').startOf('day');
  }),
  add: jest.requireActual('dayjs')(`2020-08-18 12:00:00`),
}));

describe('getEarliestDate Function', () => {
  it('should return earliest date response', () => {
    const earliestDate = abc.getEarliestDate();
    expect(earliestDate).toMatch(dayjs().add(121, 'minute').format('YYYY-MM-DD HH:mm'));
  });

但是得到这个: TypeError: dayjs_1.default 不是一个函数 任何帮助/建议都将不胜感激。

你能给我们提供使用代码吗? - Antoine Eskaros
3个回答

6
MockDate非常适合这个场景,无需编写复杂的模拟代码。

https://www.npmjs.com/package/mockdate

import MockDate from 'mockdate'
import dayjs from 'dayjs'

MockDate.set('2000-11-22')
console.log(dayjs.format())

// >>> 2000-11-22T00:00:00Z


记得在测试后使用以下代码清除模拟数据: MockDate.reset();

1
这个解决方案非常棒,毫不费力地工作了。非常感谢。 - Arif Shaikh

4

以下代码可用于 dayjs 的基本操作:

jest.mock('dayjs', () => jest.fn((...args) => jest.requireActual('dayjs')(args.filter((arg) => arg).length > 0 ? args : '2020-08-12')),);

当'2020-08-12'是你想要模拟的日期时。


1
我认为问题在于模拟的模块的default函数应该是函数本身,而不是dayjs()返回结果。尝试以下代码即可解决问题:
jest.mock('dayjs', () => ({
  default: jest.fn((...args) => {
    const yourDay = jest.requireActual('dayjs')(args.filter((arg) => arg).length > 0 ? args : '2020-08-11');
    // Mock add function
    yourDay.add = jest.fn(() => jest.requireActual('dayjs')(`2020-08-10 12:00:00`));
    // more mock
    return yourDay;
  })
}));

还要删除另一个模拟,因为它将替换:

jest.mock('dayjs', () => ({
  default: jest.requireActual('dayjs')(`2020-08-18 12:00:00`),
  extend: jest.fn(),
  // ...
}));

另一个解决方案是,您可以更改并保留第一个模型的不变性:
jest.mock('dayjs', () =>
  jest.fn((...args) => jest.requireActual('dayjs')(args.filter((arg) => arg).length > 0 ? args : '2020-08-12')),
);

您需要做的唯一一件事就是在您的tsconfig.json中启用选项 esModuleInterop ,因为这个选项会自动为您添加 default 函数:
{
  "compilerOptions": {
    // ...
    "esModuleInterop": true,
  },
}

谢谢您的回复。我还需要模拟其他函数,比如 .utc() 和 .add(),我该怎么做呢? - Mohammed Amir Ansari
1
我在答案中又留下了更多的想法给你。 - tmhao2005
我遇到了这个问题,说实话,我并不是很理解这个例子。如果能提供更多的解释,我认为这个答案会更好。我点赞是因为作者付出了很大的努力。谢谢。 - aisflat439
你们想出解决方案了吗?我真的需要一个。 - Roger Perez
对我来说,我最终通过 jest.mock('dayjs', () => ({ default: jest.requireActual('dayjs') })); 成功了。 - thorne51

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接