Scherz: Besserer Weg, um die Konsole in Unit-Tests zu deaktivieren

91

Ich frage mich, ob es eine bessere Möglichkeit gibt , Konsolenfehler innerhalb eines bestimmten Jest-Tests zu deaktivieren (dh die ursprüngliche Konsole vor / nach jedem Test wiederherzustellen ).

Hier ist mein aktueller Ansatz:

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");
  });
});

Gibt es einen saubereren Weg, um dasselbe zu erreichen? Ich würde gerne vermeiden spyOn, mockRestorescheint aber nur damit zu arbeiten .

Vielen Dank!

Apidcloud
quelle

Antworten:

125

Für bestimmte Spezifikationsdateien ist Andreas gut genug. Das folgende Setup unterdrückt console.logAnweisungen für alle Testsuiten.

jest --silent

(oder)

Zum Anpassen können warn, info and debugSie das folgende Setup verwenden

__tests __ / setup.js oder jest-pretoad.js konfiguriert insetupFilesAfterEnv

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 Hinweis: setupTestFrameworkScriptFile ist zugunsten von setupFilesAfterEnv veraltet.

module.exports = {
    verbose: true,
    setupFilesAfterEnv: ["<rootDir>/__tests__/setup.js"],
};
Raja Jaganathan
quelle
2
Hallo! setupTestFrameworkScriptFilewird zugunsten von abgelehnt setupFilesAfterEnv.
Elhoucin
1
Das Verspotten global.consoleist in der Tat ein einfacher Weg und kann über jede konfigurierte Methode erfolgen setupFilesAfterEnv . Achten Sie darauf, alle nativen Methoden des consoleObjekts zu verspotten, da sonst andere unerwartete Fehler auftreten können.
Vadorequest
49

Da jede Testdatei in einem eigenen Thread ausgeführt wird, muss sie nicht wiederhergestellt werden, wenn Sie sie für alle Tests in einer Datei deaktivieren möchten. Aus dem gleichen Grund können Sie auch einfach schreiben

console.log = jest.fn()
expect(console.log).toHaveBeenCalled();
Andreas Köberle
quelle
1
Vielen Dank für die Infos zu diesem Thema. Es macht Sinn :) Ich habe nach einer Möglichkeit gesucht, dies nur innerhalb eines bestimmten Tests so zu machen, ohne es wiederherstellen zu müssen (ich dachte anfangs, dass dies standardmäßig das Verhalten ist), aber ich denke, bevor jeder den Trick macht.
Apidcloud
46

Wenn Sie es nur für einen bestimmten Test tun möchten:

beforeEach(() => {
  jest.spyOn(console, 'warn').mockImplementation(() => {});
});
Constantin
quelle
1
das ist brilliant!
sheriff_paul
20

Ich fand , dass die Antwort oben Re: Unterdrückung der console.logüber alle Testsuiten Fehler warf , wenn alle anderen consoleMethoden (zB warn, error) genannt wurden , da es wurde die gesamte globale ersetzen consoleObjekt.

Dieser etwas ähnliche Ansatz hat bei mir mit Jest 22+ funktioniert:

package.json

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

jest / setup.js

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

Bei Verwendung dieser Methode wird nur console.logverspottet und andere consoleMethoden bleiben davon unberührt.

Nickb
quelle
6

Für mich ist ein klarer / sauberer Weg (der Leser benötigt wenig Wissen über die Scherz-API, um zu verstehen, was passiert), einfach manuell das zu tun, was mockRestore tut:

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

// at end of test
console.log = consoleLog;
Michael Liquori
quelle
1
Sie müssen auch console.info, console.error, console.warn usw.
abdecken
1
@ michael-liquori warum musst du die console.log neu starten? Ich denke, nach jeder Beschreibung sind die Verspottungen beseitigt
Jhonatan
2
@Jhonatan Ich glaube nicht, dass es nach jeder Beschreibung klar wird, obwohl ich dies kürzlich nicht getestet habe, um sicherzugehen. Laut Scherzdokumenten gibt es eine clearMocksund resetMocksKonfigurationsoption, aber beide sind standardmäßig aktiviert false, und keiner von beiden stellt die ursprüngliche Implementierung tatsächlich wieder her, selbst wenn sie auf gesetzt ist true. Und da dies eine Konfigurationsoption ist, die irgendwann geändert werden könnte, ist es meiner Meinung nach empfehlenswert, manuell zu bereinigen, um sicherzustellen, dass Ihre Tests in Zukunft keine Probleme verursachen.
Michael Liquori
-1

Ein anderer Ansatz ist zu verwenden process.env.NODE_ENV. Auf diese Weise kann man selektiv auswählen, was beim Ausführen von Tests angezeigt werden soll (oder nicht):

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');
}

oder

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

Dazu muss diese Konfiguration aktiviert sein package.json:

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

Beachten Sie, dass dieser Ansatz keine direkte Lösung für die ursprüngliche Frage darstellt, sondern das erwartete Ergebnis liefert, solange die Möglichkeit besteht, das console.logmit der genannten Bedingung zu versehen.

Wallace Sidhrée
quelle
1
Der Autor der Frage ist, wie die Datei console.log beim Testen deaktiviert wird. Diese Lösung ist nicht optimal.
Erick
Für Copy-Paster da draußen: Ersetzen Sie ===durch !==nach Ihren Wünschen. Ich benutze diesen Ansatz seit Jahren und er funktioniert einwandfrei, aber ich nehme Anpassungen entsprechend meinen Bedürfnissen vor.
Wallace Sidhrée
Beantwortet die eigentliche Frage nicht.
Michael Oryl
Dies ist eine hackige Lösung und nicht anpassbar. Was ist, wenn nur für einen bestimmten Test und nicht für den anderen deaktiviert wird?
Jhonatan