Búsqueda de sitios web

jestjs - La cobertura de Jest se comporta de manera extraña en declaraciones if simples usando TypeScript


Parece que jest no es capaz de cubrir ni una sola instrucción if. Esta es una función que quiero probar :

...  
load(): void {
    glob.sync('**/*.docs.json').forEach((file) => {
      const f = require(file);

      if (f.tags) this.doc.tags = f.tags;
});

Escribí la siguiente prueba:

import path from 'path';

import Sample from './sample';

const mockedJsonConfigFile = __dirname + '/test.json';

jest.mock('glob', () => {
  return {
    sync: () => [mockedJsonConfigFile],
  };
});

describe('Sample test', () => {
  let sample: Sample;

  beforeAll(() => {
    sample = new Sample();
  });

  it('Should load file correctly', () => {
    const mockResolveFile = jest.spyOn(path, 'resolve');

    sample.load();

    let jsonFileCalled = false;
    // check if the json file is called
    mockResolveFile.mock.calls.forEach((c) => {
      if (typeof c == 'object' && c.includes(mockedJsonConfigFile)) {
        jsonFileCalled = true;
      }
    });

    expect(jsonFileCalled).toBeTruthy();
    expect(sample.doc.tags.length).toBe(2);
  });
});

Carga un archivo de configuración que contiene un objeto de 2 etiquetas:

{
  "tags": ["tag1", "tag2"]
}

Así que cuando ejecuto la prueba, me dice que la línea 15 (sentencia if) no está cubierta, pero no entiendo por qué, ya que mi prueba especifica que debería tener 2 elementos en el arreglo de etiquetas.

¿Alguna solución para eso?

Respuesta #1

Esto no afirma exactamente lo que hace load:

expect(sample.doc.tags.length).toBe(2);

Prueba que tags es similar a un arreglo pero no exactamente qué es y una condición en la que fue asignado.

El mock actual de glob no es adecuado para este escenario de prueba porque es incondicional. Es mejor hacer que glob.sync sea un espía para que la implementación pueda cambiarse en diferentes pruebas; luego puede ser simulado para devolver rutas a distintos archivos JSON de prueba. Alternativamente, el mock de glob.sync puede permanecer igual y simularse el archivo JSON sin ningún archivo de prueba.

Se puede probar así:

jest.spyOn(glob, 'sync').mockReturnedValue([__dirname + '/test.json']);

...

const testJsonMock = { "tags": ["tag1", "tag2"] };
jest.mock(__dirname + '/test.json', () => testJsonMock);
sample.load();
expect(sample.doc.tags).toBe(testJsonMock.tags);

...

const testJsonMock = { "tags": null };
jest.mock(__dirname + '/test.json', () => testJsonMock);
sample.load();
expect(sample.doc.tags).toBeFalsy();