Jest: Lepszy sposób na wyłączenie konsoli w testach jednostkowych


91

Zastanawiam się, czy istnieje lepszy sposób niepełnosprawnymi błędów konsoli wewnątrz w konkretnym teście żartem (czyli przywrócić oryginalną konsolę przed / po każdej próbie).

Oto moje obecne podejście:

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

Czy istnieje czystszy sposób na osiągnięcie tego samego? Chciałbym tego uniknąć spyOn, ale mockRestorewydaje mi się, że to działa .

Dzięki!

Odpowiedzi:


125

Dla konkretnego pliku specyfikacji Andreas jest wystarczająco dobry. Poniższa konfiguracja pominie console.loginstrukcje dla wszystkich zestawów testów,

jest --silent

(lub)

Aby dostosować warn, info and debug, możesz użyć poniższej konfiguracji

__tests __ / setup.js lub jest-preload.js skonfigurowane wsetupFilesAfterEnv

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 Uwaga: plik setupTestFrameworkScriptFile jest przestarzały i zastępuje go setupFilesAfterEnv.

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

2
Cześć! setupTestFrameworkScriptFilejest przestarzały na korzyść setupFilesAfterEnv.
elhoucine

1
Mockowanie global.consolejest rzeczywiście prostym sposobem i można je wykonać za pomocą dowolnego skonfigurowanego setupFilesAfterEnv . Uważaj, aby kpić ze wszystkich natywnych metod consoleobiektu, bo możesz napotkać inne nieoczekiwane błędy.
Vadorequest

49

Ponieważ każdy plik testowy działa we własnym wątku, nie ma potrzeby jego przywracania, jeśli chcesz go wyłączyć dla wszystkich testów w jednym pliku. Z tego samego powodu możesz też po prostu pisać

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

1
Dziękuję za informację w tej sprawie. To ma sens :) Szukałem sposobu, aby to zrobić tylko w ramach konkretnego testu bez konieczności przywracania go (początkowo myślałem, że to zachowanie domyślne), ale chyba wcześniej każdy załatwia sprawę.
Apidcloud

46

Jeśli chcesz to zrobić tylko dla konkretnego testu:

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

1
To jest genialne!
sheriff_paul

20

Okazało się, że odpowiedź powyżej re: tłumienie console.logwe wszystkich zestawów testów wyrzucił błędy gdy wszelkie inne consolemetody (np warn, error) były nazywane, ponieważ został zastępując całą globalną consoleobiekt.

To nieco podobne podejście zadziałało u mnie w przypadku Jest 22+:

package.json

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

jest / setup.js

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

Korzystanie z tej metody console.logjest tylko wyszydzane, a inne consolemetody pozostają niezmienione.


6

Dla mnie bardziej przejrzystym sposobem (czytelnik potrzebuje niewielkiej wiedzy na temat API jest, aby zrozumieć, co się dzieje), jest ręczne zrobienie tego, co robi mockRestore:

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

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

1
Musisz także zakryć console.info, console.error, console.warn, itp.
Michael Oryl

1
@ michael-liquori dlaczego musisz zrestartować console.log? Myślę, że po każdym opisie kpiny są usuwane
Jhonatan,

2
@Jhonatan Nie sądzę, żeby było to jasne po każdym opisie, chociaż ostatnio nie testowałem tego, aby mieć pewność. Według żartem docs jest clearMocksi resetMockskonfiguracja opcji, ale oboje domyślnie false, a żadna z tych faktycznie przywrócić początkową realizację nawet jeśli jest ustawiony na true. Biorąc pod uwagę, że jest to opcja konfiguracji, którą można zmienić w pewnym momencie, myślę, że najlepszą praktyką jest ręczne czyszczenie, aby upewnić się, że testy nie spowodują problemów w przyszłości.
Michael Liquori

-1

Innym podejściem jest użycie process.env.NODE_ENV. W ten sposób można wybiórczo wybrać, co wyświetlać (a czego nie) podczas uruchamiania testów:

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

lub

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

Będzie to wymagało umieszczenia tej konfiguracji na package.json:

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

Zwróć uwagę, że takie podejście nie jest bezpośrednim rozwiązaniem pierwotnego pytania, ale daje oczekiwany rezultat, o ile ma się możliwość objęcia console.logwspomnianego warunku.


1
Autor pytania, jak wyłączyć console.log podczas testowania. To rozwiązanie nie jest optymalne.
Erick

Dla kopiowaniem pasters tam zamienić ===się !==w zależności od potrzeb. Stosuję to podejście od lat i działa bezbłędnie, ale dostosowuję się do moich potrzeb.
Wallace Sidhrée

Nie odpowiada na właściwe pytanie.
Michael Oryl

To hackerskie rozwiązanie, którego nie można dostosowywać. Co się stanie, jeśli wyłącz tylko dla konkretnego testu, a nie dla drugiego?
Jhonatan
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.