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.