使用玩笑嘲笑一下moment()和moment()。format

时间:2019-04-24 21:26:17

标签: javascript reactjs unit-testing jestjs momentjs

我无法模拟moment()或moment()。format函数。我有状态,currentDateMoment和currentDateFormatted被设置如下。

currentDateMoment: moment() //2019-04-23T17:45:26.339Z currentDateFormatted: moment().format('MM-DD-YYYY').valueOf() //"04-23-2019"

尝试在快照测试中同时模拟一下moment()和moment()。format以返回特定日期,但无法执行。尝试过以下。

jest.mock('moment', () => () => '2018–01–30T12:34:56+00:00');

jest.mock('moment', () => ({
constructor: () => '2018–01–30T12:34:56+00:00'
})); 

jest.mock('moment', () => () => ({ format: () => '01– 
30-2018' }));

7 个答案:

答案 0 :(得分:10)

您可以模拟Moment以返回特定日期,然后不必模拟format

jest.mock('moment', () => {
  return () => jest.requireActual('moment')('2020-01-01T00:00:00.000Z');
});

这样做,对Moment()的任何调用都将始终返回一个时刻对象,该对象的日期设置为 2020-01-01 00:00:00

这里是一个示例,该函数返回明天的日期和对该函数的测试。

const moment = require('moment');
const tomorrow = () => {
  const now = moment();
  return now.add(1, 'days');
};

describe('tomorrow', () => {
  it('should return the next day in a specific format', () => {
    const date = tomorrow().format('YYYY-MM-DD');
    expect(date).toEqual('2020-01-02');
  });
});

答案 1 :(得分:10)

模拟moment()及其使用的任何函数(即.day().format())的最简单方法是更改​​Date所使用的moment()

在测试文件中添加以下代码段

Date.now = jest.fn(() => new Date("2020-05-13T12:33:37.000Z"));

因此,在测试中随时调用moment()时,moment()认为今天是2020年5月13日,星期三。

答案 2 :(得分:2)

mockdate为我工作

import mockDate from "mockdate";


test('Should add some', () => {
    mockDate.set(new Date('2/20/2020'));

    const action = addSome();

    expect(action).toEqual({
        createdAt: moment()
    });

    mockDate.reset();
})

答案 3 :(得分:1)

这是解决方案:

index.ts

import moment from 'moment';

export function main() {
  return {
    currentDateMoment: moment().format(),
    currentDateFormatted: moment()
      .format('MM-DD-YYYY')
      .valueOf()
  };
}

index.spec.ts

import { main } from './';
import moment from 'moment';

jest.mock('moment', () => {
  const mMoment = {
    format: jest.fn().mockReturnThis(),
    valueOf: jest.fn()
  };
  return jest.fn(() => mMoment);
});

describe('main', () => {
  test('should mock moment() and moment().format() correctly ', () => {
    (moment().format as jest.MockedFunction<any>)
      .mockReturnValueOnce('2018–01–30T12:34:56+00:00')
      .mockReturnValueOnce('01–30-2018');
    expect(jest.isMockFunction(moment)).toBeTruthy();
    expect(jest.isMockFunction(moment().format)).toBeTruthy();
    const actualValue = main();
    expect(actualValue).toEqual({ currentDateMoment: '2018–01–30T12:34:56+00:00', currentDateFormatted: '01–30-2018' });
  });
});

覆盖率100%的单元测试结果:

 PASS  src/stackoverflow/55838798/index.spec.ts
  main
    ✓ should mock moment() and moment().format() correctly  (7ms)

----------|----------|----------|----------|----------|-------------------|
File      |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files |      100 |      100 |      100 |      100 |                   |
 index.ts |      100 |      100 |      100 |      100 |                   |
----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        3.795s, estimated 8s

源代码:https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/55838798

答案 4 :(得分:0)

模拟Moment().format()startOf()isValid()isAfter()等。可以参考下面的示例。

jest.mock('moment', () => {
    
    const momentParams = {
        format: jest.fn(() => '10/04/2020'),
        startOf: jest.fn().mockReturnThis(),
        isAfter: jest.fn().mockReturnValue(true),
        isValid: jest.fn().mockReturnValue(true)
    };

   const fn = jest.fn(newMoment => {
        momentParams.format = jest.fn(() => newMoment);
        return momentParams;
   });

   return fn;
});

最后,您可以编写一个这样的测试用例。 例如。

 test('should returned mocked value for isAfter()', async () => {
    jest.spyOn(moment(), 'isAfter').mockReturnValue(false);
    const response = moment().isAfter();
    expect(response).toBe(false)
})

答案 5 :(得分:0)

其他答案告诉您如何模拟时刻,但您不需要模拟时刻来测试该代码。需要。事实上,你可能不应该这样做;这是一个复杂的第三方接口,您并不拥有它,并且模拟它会将您的测试与它结合起来,您最终会测试实现而不是行为

不是不带任何参数调用 moment(),而是使用当前日期调用它(每个 https://momentjscom.readthedocs.io/en/latest/moment/01-parsing/01-now/ moment() 基本上是 moment(new Date()))。那么当前日期来自您确实拥有的一个函数:

const { getCurrentDate } = require('path/to/utils');

export const createSomething =() => ({
  currentDateMoment: moment(getCurrentDate()),
  currentDateFormatted: moment(getCurrentDate()).format('MM-DD-YYYY'),
});

所以你可以在测试中简单地模拟它:

const { createSomething } = require('path/to/impl');
const { getCurrentDate } = require('path/to/utils');
jest.mock('path/to/utils');

it('formats the data correctly', () => {
  getCurrentDate.mockReturnValue(new Date(2021, 3, 29));

  const { currentDateFormatted } = createSomething();
  expect(currentDateFormatted).toEqual('2021-04-29');
});

现在测试根本不涉及已经成为实现细节的时刻。如果未来的瞬间 API 发生了重大变化,您会发现它,因为您的测试将失败;如果它被嘲笑,他们会误导性地通过。如果您想切换到不同的库,您可以这样做,确信测试意味着 行为 仍然是正确的(here's 一个使用 DayJS 做同样事情的示例)。

答案 6 :(得分:-1)

我仍然遇到一些错误,因为我也使用了矩时区。因此,这是我为解决此问题所做的事情:

let diffMins = updateThreshold + 1;
jest.mock('moment', () => {
  const mMoment = {
    diff: jest.fn(() => diffMins),
  };
  const fn = jest.fn(() => mMoment);
  fn.version = '2.24';
  fn.tz = jest.fn();
  fn.fn = jest.fn();
  return fn;
});