Broma: mejor manera de deshabilitar la consola dentro de las pruebas unitarias

91

Me pregunto si hay una mejor manera de deshabilitar los errores de la consola dentro de una prueba Jest específica (es decir, restaurar la consola original antes / después de cada prueba).

Aquí está mi enfoque actual:

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

¿Existe una forma más limpia de lograr lo mismo? Me gustaría evitarlo spyOn, pero mockRestoresolo parece funcionar con él .

¡Gracias!

Apidcloud
fuente

Respuestas:

125

Para un archivo de especificaciones en particular, Andreas es suficientemente bueno. La siguiente configuración suprimirá las console.logdeclaraciones para todos los conjuntos de pruebas,

jest --silent

(o)

Para personalizar warn, info and debug, puede utilizar la siguiente configuración

__tests __ / setup.js o jest-preload.js configurados ensetupFilesAfterEnv

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 Nota: setupTestFrameworkScriptFile está en desuso en favor de setupFilesAfterEnv.

module.exports = {
    verbose: true,
    setupFilesAfterEnv: ["<rootDir>/__tests__/setup.js"],
};
Raja Jaganathan
fuente
2
¡Hola! setupTestFrameworkScriptFileestá en desuso a favor de setupFilesAfterEnv.
elhoucine
1
De hecho, la simulación global.consolees una forma sencilla de hacerlo y se puede realizar a través de cualquier configuración setupFilesAfterEnv . Tenga cuidado de burlarse de todos los métodos nativos del consoleobjeto o puede encontrar otros errores inesperados.
Vadorequest
49

Como cada archivo de prueba se ejecuta en su propio hilo, no es necesario restaurarlo si desea desactivarlo para todas las pruebas en un archivo. Por la misma razón, también puedes escribir

console.log = jest.fn()
expect(console.log).toHaveBeenCalled();
Andreas Köberle
fuente
1
Gracias por la información sobre ese asunto. Tiene sentido :) Estaba buscando una manera de hacerlo así solo dentro de una prueba específica sin tener que restaurarla (inicialmente pensé que ese era el comportamiento por defecto), pero supongo que antes de que cada uno haga el truco.
Apidcloud
46

Si quieres hacerlo solo para una prueba específica:

beforeEach(() => {
  jest.spyOn(console, 'warn').mockImplementation(() => {});
});
Constantin
fuente
1
¡esto es brillante!
sheriff_paul
20

Descubrí que la respuesta anterior re: suprimir console.logen todas las suites de prueba arrojaba errores cuando se llamaba a cualquier otro consolemétodo (por ejemplo warn, error) ya que reemplazaba todo el consoleobjeto global .

Este enfoque algo similar funcionó para mí con Jest 22+:

package.json

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

jest / setup.js

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

Con este método, solo console.logse burla y los demás consolemétodos no se ven afectados.

nickb
fuente
6

Para mí, una forma más clara / limpia (el lector necesita poco conocimiento de la API de broma para comprender lo que está sucediendo) es hacer manualmente lo que hace mockRestore:

// 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
fuente
1
También debe cubrir console.info, console.error, console.warn, etc.
Michael Oryl
1
@ michael-liquori ¿por qué es necesario reiniciar el archivo console.log? Creo que después de cada descripción se aclaran las burlas
Jhonatan
2
@Jhonatan No creo que quede claro después de cada descripción, aunque no lo he probado recientemente para estar seguro. De acuerdo con los documentos de jest, hay una opción de configuración clearMocksy resetMocks, pero ambas están predeterminadas false, y ninguna de ellas restaura la implementación inicial incluso si está configurada en true. Y, considerando que esta es una opción de configuración que podría cambiarse en algún momento, creo que es una buena práctica limpiar manualmente para garantizar que sus pruebas no causen problemas en el futuro.
Michael Liquori
-1

Otro enfoque es utilizar process.env.NODE_ENV. De esta manera, uno puede elegir selectivamente qué mostrar (o no) mientras se realizan las pruebas:

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

o

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

Esto requerirá que esta configuración se coloque en package.json:

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

Tenga en cuenta que este enfoque no es una solución directa a la pregunta original, pero da el resultado esperado siempre que se tenga la posibilidad de ajustarlo console.logcon la condición mencionada.

Wallace Sidhrée
fuente
1
Lo que el autor de la pregunta es cómo deshabilitar console.log en las pruebas. Esta solución no es óptima.
Erick
Para la copia-desbobinadores por ahí: sustituir ===con !==de acuerdo a sus necesidades. He estado usando este enfoque durante años y funciona perfectamente, pero hago ajustes según mis necesidades.
Wallace Sidhrée
No responde la pregunta real.
Michael Oryl
Esta es una solución pirata y no personalizable. ¿Qué pasa si se desactiva solo para una prueba específica y no para la otra?
Jhonatan