Jest: Cara yang lebih baik untuk menonaktifkan konsol di dalam unit test

91

Aku ingin tahu apakah ada cara yang lebih baik untuk kesalahan konsol menonaktifkan dalam sebuah tes Jest tertentu (yaitu, mengembalikan konsol asli sebelum / sesudah setiap tes).

Inilah pendekatan saya saat ini:

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

Adakah cara yang lebih bersih untuk mencapai hal yang sama? Saya ingin menghindari spyOn, tetapi mockRestoresepertinya hanya bekerja dengannya .

Terima kasih!

Apidcloud
sumber

Jawaban:

125

Untuk spek file tertentu, Andreas sudah cukup bagus. Penyiapan di bawah ini akan menyembunyikan console.logpernyataan untuk semua rangkaian pengujian,

jest --silent

(atau)

Untuk menyesuaikan warn, info and debugAnda dapat menggunakan pengaturan di bawah ini

__tests __ / setup.js atau jest-preload.js dikonfigurasi disetupFilesAfterEnv

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 Catatan: setupTestFrameworkScriptFile tidak digunakan lagi dan mendukung setupFilesAfterEnv.

module.exports = {
    verbose: true,
    setupFilesAfterEnv: ["<rootDir>/__tests__/setup.js"],
};
Raja Jaganathan
sumber
2
Hai! setupTestFrameworkScriptFiletidak digunakan lagi karena setupFilesAfterEnv.
elhoucine
1
Mengolok global.console- olok memang cara yang sederhana, dan dapat dilakukan melalui konfigurasi apa pun setupFilesAfterEnv . Berhati-hatilah untuk memalsukan semua metode asli consoleobjek atau Anda mungkin mengalami kesalahan tak terduga lainnya.
Vadorequest
49

Karena setiap file pengujian berjalan di utasnya sendiri, tidak perlu memulihkannya jika Anda ingin menonaktifkannya untuk semua pengujian dalam satu file. Untuk alasan yang sama Anda juga bisa menulis

console.log = jest.fn()
expect(console.log).toHaveBeenCalled();
Andreas Köberle
sumber
1
Terima kasih atas infonya. Masuk akal :) Saya sedang mencari cara untuk membuatnya seperti itu hanya di dalam tes tertentu tanpa harus mengembalikannya (awalnya saya mengira itu adalah perilaku secara default), tetapi saya kira beforeEach melakukan triknya.
Apidcloud
46

Jika Anda ingin melakukannya hanya untuk tes tertentu:

beforeEach(() => {
  jest.spyOn(console, 'warn').mockImplementation(() => {});
});
Constantin
sumber
1
ini luar biasa!
sheriff_paul
20

Saya menemukan bahwa jawaban di atas re: menekan console.logdi semua rangkaian pengujian menimbulkan kesalahan ketika consolemetode lain (misalnya warn, error) dipanggil karena itu menggantikan seluruh consoleobjek global .

Pendekatan yang agak mirip ini berhasil untuk saya dengan Jest 22+:

package.json

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

jest / setup.js

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

Menggunakan metode ini, hanya console.logdiejek dan consolemetode lain tidak terpengaruh.

nickb
sumber
6

Bagi saya cara yang lebih jelas / bersih (pembaca membutuhkan sedikit pengetahuan tentang API lelucon untuk memahami apa yang terjadi), adalah dengan melakukan apa yang dilakukan mockRestore secara manual:

// 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
sumber
1
Anda juga perlu menutupi console.info, console.error, console.warn, dll.
Michael Oryl
1
@ michael-liquori mengapa Anda perlu memulai ulang console.log? Saya pikir setelah setiap menggambarkan olok-olok itu dihapus
Jhonatan
2
@Jhonatan Saya pikir itu tidak jelas setelah setiap penjelasan, meskipun saya belum menguji ini baru-baru ini untuk memastikan. Menurut dokumen jest ada opsi clearMocksdan resetMockskonfigurasi tetapi keduanya default false, dan tidak satu pun dari mereka yang benar-benar memulihkan implementasi awal bahkan jika disetel ke true. Dan, mengingat ini adalah opsi konfigurasi yang dapat diubah di beberapa titik, menurut saya praktik terbaik adalah membersihkan secara manual untuk memastikan pengujian Anda tidak akan menimbulkan masalah di masa mendatang.
Michael Liquori
-1

Pendekatan lain adalah dengan menggunakan process.env.NODE_ENV. Dengan cara ini seseorang dapat secara selektif memilih apa yang akan ditampilkan (atau tidak) saat menjalankan tes:

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

atau

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

Ini akan membutuhkan konfigurasi ini untuk ditempatkan pada package.json:

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

Perhatikan bahwa pendekatan ini bukanlah solusi langsung untuk pertanyaan awal, tetapi memberikan hasil yang diharapkan selama seseorang memiliki kemungkinan untuk membungkusnya console.logdengan kondisi yang disebutkan.

Wallace Sidhrée
sumber
1
Apa penulis pertanyaannya adalah bagaimana menonaktifkan console.log pada pengujian. Solusi ini tidak optimal.
Erick
Untuk copy-paster di luar sana: ganti ===dengan yang !==Anda butuhkan. Saya telah menggunakan pendekatan ini selama bertahun-tahun dan berhasil dengan sempurna, tetapi saya melakukan penyesuaian sesuai kebutuhan saya.
Wallace Sidhrée
Tidak menjawab pertanyaan sebenarnya.
Michael Oryl
Ini adalah solusi hacky dan tidak dapat disesuaikan. Bagaimana jika menonaktifkan hanya untuk tes tertentu dan bukan yang lain?
Jhonatan