Jest Expected 和 receive 是一样的

Jest Expected and receive are identical

为什么 Jest 会在两者看起来完全相同时将其视为不相同?

所以这是我用来做测试的代码,它基本上只是一个调用事件发射器的函数,在事件发射器中如果日期无效,我就让它保持原样:

  const datepickerComponent: Datepicker = new Datepicker();

  const mockEvent = {
    target: {
      classList: {
        remove: jest.fn(),
        add: jest.fn(),
      },
      value: '01-01-197',
    },
  } as unknown as InputEvent;

  datepickerComponent.onInput(mockEvent);

  const emitMock: jest.Mock = jest.fn();
  datepickerComponent.dsdDatepickerInputChange = { emit: emitMock } as unknown as EventEmitter<dsdDatepickerInputChangeEvent>;

  // when
  datepickerComponent.onInput(mockEvent);

  const dateValue = new Date('197-01-01T00:00:00');

  // then
  expect(emitMock).toHaveBeenCalledWith({ value: '197-01-01', valueAsDate: dateValue });

您观察到此错误的原因 是因为虽然 Date { NaN } 值看起来相同,但它们实际上引用不同的对象实例并且无法遍历相等性此外,因此实际错误应该如下:

Expected: {"value": "197-01-01", "valueAsDate": Date { NaN }}
Received: serializes to the same string

(要重现此错误 - 使用 new Date('197-01-01T00:00:00') 创建两个新日期并将它们传递到 .equals()

要克服此错误,您需要做的就是简单地将 .toHaveBeenCalledWith 测试重构为以下内容:

const calledWithArg = emitMock.mock.calls[0][0];
expect(JSON.stringify(calledWithArg)).toEqual(JSON.stringify({ value: '197-01-01', valueAsDate: dateValue }));

.toHaveBeenCalledWith 不起作用的原因是因为它不允许我们在比较之前重塑参数对象(在我们的例子中,我们需要 stringify 它), 因此我们可以选择通过 .mock.calls[0][0], stringify 提取 mock 调用的参数,然后将其与 stringified 预期对象的版本。

valueAsDate 的引用不同。但是 Jest doc 确认它使用 .toEqual 进行比较。这意味着它会尝试深入比较两个 new Date。这是个坏主意,你无法控制日期 class,而且里面可能有一些活动部件。

要松散匹配一个值,你可以检查这个问题: