开玩笑:禁用单元测试中的控制台的更好方法


91

我不知道是否有更好的方式禁用错误控制台 里面一个特定的玩笑测试(即,恢复原来的控制台/前每次测试后)。

这是我目前的方法:

describe("Some description", () => {
  let consoleSpy;

  beforeEach(() => {
    if (typeof consoleSpy === "function") {
      consoleSpy.mockRestore();
    }
  });

  test("Some test that should not output errors to jest console", () => {
    expect.assertions(2);

    consoleSpy = jest.spyOn(console, "error").mockImplementation();

    // some function that uses console error
    expect(someFunction).toBe("X");
    expect(consoleSpy).toHaveBeenCalled();
  });

  test("Test that has console available", () => {
    // shows up during jest watch test, just as intended
    console.error("test");
  });
});

有没有更干净的方法来完成同一件事?我想避免spyOn,但mockRestore似乎只能使用它

谢谢!

Answers:


125

对于特定的规范文件,Andreas的文件已经足够了。下面的设置将禁止console.log所有测试套件的语句,

jest --silent

(要么)

要自定义,warn, info and debug您可以使用以下设置

在中配置的__tests __ / setup.js jest-preload.jssetupFilesAfterEnv

global.console = {
  log: jest.fn(), // console.log are ignored in tests

  // Keep native behaviour for other methods, use those to print out things in your own tests, not `console.log`
  error: console.error,
  warn: console.warn,
  info: console.info,
  debug: console.debug,
};

jest.config.js

module.exports = {
    verbose: true,
    setupTestFrameworkScriptFile: "<rootDir>/__tests__/setup.js",
};

Jest v24.x注意:不建议使用setupTestFrameworkScriptFile,而应使用setupFilesAfterEnv。

module.exports = {
    verbose: true,
    setupFilesAfterEnv: ["<rootDir>/__tests__/setup.js"],
};

2
嗨!setupTestFrameworkScriptFile不推荐使用setupFilesAfterEnv
elhoucine

1
模拟global.console确实是一种简单的方法,可以通过任何configure来完成setupFilesAfterEnv 。当心模拟console对象的所有本机方法,否则您可能会遇到其他意外错误。
Vadorequest,

49

由于每个测试文件都在其自己的线程中运行,因此如果要对一个文件中的所有测试禁用它,则无需还原它。出于同样的原因,您也可以只写

console.log = jest.fn()
expect(console.log).toHaveBeenCalled();

1
感谢您提供有关此事的信息。它确实是有道理的:)我一直在寻找一种方法,使其仅在特定测试中才能做到这一点,而不必还原它(我最初认为默认情况下是这种行为),但是我想beforeEach可以做到这一点。
Apidcloud '17

46

如果您只想进行特定的测试:

beforeEach(() => {
  jest.spyOn(console, 'warn').mockImplementation(() => {});
});

1
这太棒了!
sheriff_paul

20

我发现上述答案是:console.log在调用所有其他console方法(例如)时,抑制所有测试套件会引发错误warnerror因为它正在替换整个全局console对象。

这种与Jest 22+相似的方法对我有用:

package.json

"jest": {
  "setupFiles": [...],
  "setupTestFrameworkScriptFile": "<rootDir>/jest/setup.js",
  ...
}

开玩笑/setup.js

jest.spyOn(global.console, 'log').mockImplementation(() => jest.fn());

使用此方法,仅console.log被模拟,其他console方法不受影响。


6

对我来说,一种更清晰/干净的方法(读者几乎不需要了解Jest API就能了解正在发生的事情),就是手动执行嘲笑还原操作:

// at start of test you want to suppress
const consoleLog = console.log;
console.log = jest.fn();

// at end of test
console.log = consoleLog;

1
您还需要盖console.info,console.error,console.warn等
迈克尔Oryl

1
@ michael-liquori为什么需要重新启动console.log?我认为在每一次描述都被清除后,嘲笑就得到了解决
约旦

2
@Jhonatan我认为每次描述后都不会清楚,尽管我最近没有做过确定性的测试。根据jest docs的说法,有一个clearMocksresetMocks配置选项,但它们都默认为false并且即使将设置为也不会真正恢复初始实现true。而且,考虑到这是一个可以在某个时候更改的配置选项,我认为最好手动进行清理以确保将来的测试不会引起问题。
Michael Liquori

-1

另一种方法是使用process.env.NODE_ENV这样一来,用户可以在运行测试时有选择地选择显示(或不显示)什么:

if (process.env.NODE_ENV === 'development') {
  console.log('Show output only while in "development" mode');
} else if (process.env.NODE_ENV === 'test') {
  console.log('Show output only while in "test" mode');
}

要么

const logDev = msg => {
  if (process.env.NODE_ENV === 'development') {
    console.log(msg);
  }
}
logDev('Show output only while in "development" mode');

这将需要将该配置放在package.json

"jest": {
  "globals": {
    "NODE_ENV": "test"
  }
}

请注意,这种方法不是直接解决原始问题的方法,但是只要可以将console.log条件包装为上述条件,就可以给出预期的结果。


1
问题的作者是如何在测试中禁用console.log。该解决方案不是最佳的。
Erick

对于复制pasters在那里:更换===!==根据您的需要。我使用这种方法已经有好几年了,并且可以正常工作,但是我会根据需要进行调整。
华莱士·西德瑞(WallaceSidhrée),

不回答实际问题。
Michael Oryl

这是一个骇人听闻的解决方案,无法自定义。如果仅对特定测试禁用而不对其他测试禁用怎么办?
Jhonatan
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.