首页 > 解决方案 > 我如何开玩笑地模拟对构造函数的调用

问题描述

正如标题所说,我在嘲笑new Date()Jest 中对构造函数的调用时遇到了一些困难。我通过返回一个特定的日期时间来模拟这个调用,以确保我的测试不会失败。但是,由于在我正在测试的函数中调用了日期构造函数两次,因此第二次调用也对其实现进行了模拟,不应模拟第二次调用。

我在下面提供了一个上下文示例,它是一个返回明天之前的秒数的小函数,因此需要模拟一个一致的现在时间。

任何帮助都会有很大帮助,我已经通过 Stack Overflow 和 Jest 文档进行了搜索。

提前致谢。

功能

function getSecondsToTomorrow() {
  // This call needs to be mocked to always return the same date time
  const now = new Date();
  
  // This call should not be mocked
  const tomorrow = new Date(
    now.getFullYear(), 
    now.getMonth(), 
    now.getDate() + 1,
    );

  return Math.round( (tomorrow - now) / 1000);
}

测试

describe("getSecondsToTomorrow()", () => {
  let result, mockDate, now;

  beforeAll(() => {
    now = new Date(2020, 7, 3, 23, 0, 0);
    mockDate = jest.spyOn(global, "Date").mockImplementation(() => now);
    result = getSecondsToTomorrow();
  });


  afterAll(() => {
    mockDate.mockRestore();
  });

  it("should return the number of seconds until tomorrow, from the time the function was called", () => {
    // We mock the date to be 2300, so the return should be 1 hour (3600 seconds)
    expect(result).toBe(3600);
  });
});

更新

虽然我仍然没有找到我的问题的具体答案,但我找到了解决方法。即使用 Jest 的mockImplementationOnce方法,我可以在第一次调用时模拟一个日期时间,new Date()并在第二次调用时将任何参数作为默认的 mockImplementation 传递。

describe("getSecondsToTomorrow()", () => {
  let result, mockDate, now, dateClone;

  function setUpDateMock(now) {
    return jest
      .spyOn(global, "Date")
      .mockImplementation((...args) => new dateClone(...args))
      .mockImplementationOnce(() => now)
  }

  beforeAll(() => {
    dateClone = Date;
    now = new Date(2020, 7, 3, 23, 0, 0);
    mockDate = setUpDateMock(now);
    result = getSecondsToTomorrow();
  });

  afterAll(() => {
    mockDate.mockRestore();
  });

  it("should return the number of seconds until tomorrow, from the time the function was called", () => {
    expect(result).toBe(3600);
  });
});

标签: javascriptunit-testingmockingjestjs

解决方案


IDK,但是克隆日期的方式对我不起作用。在第二次调用new Date()调试器时显示返回值为mockConstructor {}. 所以,我的解决方法是恢复日期:

const dateSpy = jest.spyOn(global, 'Date')
      .mockImplementationOnce(function () {
        dateSpy.mockRestore();

        return myMockedDate;
      });

推荐阅读