【问题标题】:Mock DayJs default function along with its chained methods模拟 DayJs 默认函数及其链式方法
【发布时间】:2021-01-01 01:49:45
【问题描述】:

我正在尝试模拟具有特定日期和时间的 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 is not a function

感谢任何帮助/建议。

【问题讨论】:

  • 能不能给一下使用代码。

标签: javascript typescript mocking jestjs dayjs


【解决方案1】:

对于 dayjs 的基本操作,此代码有效:

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

当“2020-08-12”是您要模拟的日期时。

【讨论】:

    【解决方案2】:

    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();

    【讨论】:

    • 这个解决方案很棒。毫不费力地工作。非常感谢。
    【解决方案3】:

    我认为问题在于模拟模块的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(),我该怎么做?
    • 我又在回答中给你留下了更多的想法
    • 我遇到了这个和tbh,不太明白这个例子。我认为如果提供更多说明,这个答案会有所改善。我投了赞成票,因为努力很强大。谢谢
    • 你们想出解决方案了吗?我真的需要一个。
    • 对我来说,我终于可以使用 jest.mock('dayjs', () => ({ default: jest.requireActual('dayjs') }));
    猜你喜欢
    • 1970-01-01
    • 2011-08-04
    • 2020-12-22
    • 2019-08-21
    • 2021-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多