使用jest.spyOn来模拟console.warn的实例

343 阅读1分钟

在开发一个可重用的组件时,有些情况下我们想在消费者通过一个不好的道具组合时发出警告。这篇文章介绍了如何在测试中模拟console.warn ,并验证出现不良道具组合的警告。

要测试的组件

valuedefaultValue 道具同时被通过时,下面的组件会警告消费者:

export function Input(props: React.ComponentPropsWithoutRef<"input">) {
  React.useEffect(() => {
    if (props.value !== undefined && props.defaultValue !== undefined) {
      console.warn(
        "If you are controlling `value` with state, there is no need to pass `defaultValue` - just set the default state"
      );
    }
  }, [props.value, props.defaultValue]);

  return <input className="input" {...props} />;
}

这个警告是一个重要的逻辑,我们可能想在测试中涵盖它。下面是测试的骨架:

test("Should output warning when value and defaultValue specified", () => {
  // TODO - mock `console.warn`
  render(<Input value="test" defaultValue="test" />);
  // TODO - check console.warn has been called
});

使用jest.spyOn

上一篇文章介绍了如何使用jest.spyOn 来模拟一个函数。我们可以使用jest.spyOn 来模拟console.warn

test("Should output warning when value and defaultValue specified", () => {
  const warn = jest.spyOn(console, 'warn').mockImplementation(() => {});  render(<Input value="test" defaultValue="test" />);
  // TODO - check console.warn has been called
});

模拟实现不需要做任何事情--主要的是我们可以检测到它被调用。

我们可以使用toBeCalledWith 匹配器来检查console.warn 是否被调用:

test("Should output warning when value and defaultValue specified", () => {
  const warn = jest.spyOn(console, "warn").mockImplementation(() => {});
  render(<Input value="test" defaultValue="test" />);
  expect(warn).toBeCalledWith(    "If you are controlling `value` with state, there is no need to pass `defaultValue` - just set the default state"  );});

在测试结束时,我们可以调用mockRestore 来清除所有的模拟统计,并恢复原始的console.warn 的实现:

test("Should output warning when value and defaultValue specified", () => {
  const warn = jest.spyOn(console, "warn").mockImplementation(() => {});
  render(<Input value="test" defaultValue="test" />);
  expect(warn).toBeCalledWith(
    "If you are controlling `value` with state, there is no need to pass `defaultValue` - just set the default state"
  );
  warn.mockRestore();});

很好!😊

本帖的代码可以在Codesandbox中找到,链接如下:

🏃 玩转该代码