Búsqueda de sitios web

typescript - En Jest, ¿cómo simulo un módulo externo SOLO en una prueba específica?


Estoy usando Jest con TypeScript (usando ts-jest). Este es mi sujeto de prueba que usa la biblioteca dotenv:

import * as dotenv from 'dotenv';

export class TestSubject {
  public function test() {
    console.log(dotenv); // Here I debug if I'm using a mock or not
  }
}

Me gustaría simular la biblioteca dotenv solo para una prueba específica, pero estoy atascado.

Aquí está mi conjunto de pruebas:

import { TestSubject } from './test-subject';
import * as dotenv from 'dotenv';

jest.mock('dotenv'); // place it here, otherwise it doesn't work

describe('Suite 1', () => {
  it('test 1', () => {
    // I want to use the mock here... and it works
    const subject = new TestSubject();
    subject.test(); // shows that I'm using the mock
  });

  it('test 2', () => {
    // I don't want the mock here
    jest.dontMock('dotenv'); // doesn't work
    jest.unmock('dotenv');   // doesn't work

    const subject = new TestSubject();
    subject.test(); // shows that I'm still using the mock!!!
  });
});

Como puedes ver, la llamada jest.mock('dotenv') debe colocarse fuera de describe, de lo contrario, no funciona.

Estoy tratando de no usar el mock en test 2, pero no funciona: console.log muestra que estoy usando el mock.

Respuesta #1

Una mejora a la solución de @slideshowp2.

Con jest.domock necesitas llamar a require después al módulo (como aquí), pero el resultado de require tiene el tipo any y perdemos la seguridad de tipos. así que puedes usar las importaciones dinámicas de TypeScript.

Ejemplo de código completo:

import * as summer from './exampleModule';

describe('mock vs no-mock', () => {
    beforeEach(() => {
        jest.resetModules();
    });

    it('NO-MOCKED', async () => {
        console.log(summer.sum(1, 1));
        expect(summer.sum(1, 1)).toBe(2);
    });
    it('MOCKED', async () => {
        jest.doMock('./exampleModule');
        const summer = await import('./exampleModule');

        const mockedSummer = mocked(summer, true);
        mockedSummer.sum.mockImplementation((a, b) => a + b + 1);
        console.log(summer.sum(1, 1));
        expect(summer.sum(1, 1)).toBe(3);
    });
    it('NO-MOCKED', async () => {
        console.log(summer.sum(1, 1));
        expect(summer.sum(1, 1)).toBe(2);
    });
});

Respuesta #2

Aquí está la solución:

index.ts, el archivo será probado:

import * as dotenv from 'dotenv';

export class TestSubject {
  public test() {
    console.log(dotenv);
  }
}

Prueba unitaria:

describe('TestSubject', () => {
  beforeEach(() => {
    jest.resetModules();
  });
  it('should mock dotenv', () => {
    jest.doMock('dotenv');
    const dotenv = require('dotenv');
    const { TestSubject } = require('./');
    const subject = new TestSubject();
    subject.test();
    expect(jest.isMockFunction(dotenv.config)).toBeTruthy();
  });

  it('should not mock dotenv', () => {
    jest.unmock('dotenv');
    const dotenv = require('dotenv');
    const { TestSubject } = require('./');
    const subject = new TestSubject();
    subject.test();
    expect(jest.isMockFunction(dotenv.config)).toBeFalsy();
  });
});

Resultado de la prueba unitaria:

 PASS  src/stackoverflow/56446543/index.spec.ts
  TestSubject
    ✓ should mock dotenv (2111ms)
    ✓ should not mock dotenv (2ms)

  console.log src/stackoverflow/56446543/index.ts:5
    { config: 
       { [Function: config]
         _isMockFunction: true,
         getMockImplementation: [Function],
         mock: [Getter/Setter],
         mockClear: [Function],
         mockReset: [Function],
         mockRestore: [Function],
         mockReturnValueOnce: [Function],
         mockResolvedValueOnce: [Function],
         mockRejectedValueOnce: [Function],
         mockReturnValue: [Function],
         mockResolvedValue: [Function],
         mockRejectedValue: [Function],
         mockImplementationOnce: [Function],
         mockImplementation: [Function],
         mockReturnThis: [Function],
         mockName: [Function],
         getMockName: [Function] },
      parse: 
       { [Function: parse]
         _isMockFunction: true,
         getMockImplementation: [Function],
         mock: [Getter/Setter],
         mockClear: [Function],
         mockReset: [Function],
         mockRestore: [Function],
         mockReturnValueOnce: [Function],
         mockResolvedValueOnce: [Function],
         mockRejectedValueOnce: [Function],
         mockReturnValue: [Function],
         mockResolvedValue: [Function],
         mockRejectedValue: [Function],
         mockImplementationOnce: [Function],
         mockImplementation: [Function],
         mockReturnThis: [Function],
         mockName: [Function],
         getMockName: [Function] },
      default: 
       { config: 
          { [Function: config]
            _isMockFunction: true,
            getMockImplementation: [Function],
            mock: [Getter/Setter],
            mockClear: [Function],
            mockReset: [Function],
            mockRestore: [Function],
            mockReturnValueOnce: [Function],
            mockResolvedValueOnce: [Function],
            mockRejectedValueOnce: [Function],
            mockReturnValue: [Function],
            mockResolvedValue: [Function],
            mockRejectedValue: [Function],
            mockImplementationOnce: [Function],
            mockImplementation: [Function],
            mockReturnThis: [Function],
            mockName: [Function],
            getMockName: [Function] },
         parse: 
          { [Function: parse]
            _isMockFunction: true,
            getMockImplementation: [Function],
            mock: [Getter/Setter],
            mockClear: [Function],
            mockReset: [Function],
            mockRestore: [Function],
            mockReturnValueOnce: [Function],
            mockResolvedValueOnce: [Function],
            mockRejectedValueOnce: [Function],
            mockReturnValue: [Function],
            mockResolvedValue: [Function],
            mockRejectedValue: [Function],
            mockImplementationOnce: [Function],
            mockImplementation: [Function],
            mockReturnThis: [Function],
            mockName: [Function],
            getMockName: [Function] } } }

  console.log src/stackoverflow/56446543/index.ts:5
    { config: [Function: config],
      parse: [Function: parse],
      default: { config: [Function: config], parse: [Function: parse] } }

Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        3.394s, estimated 4s

Como puedes ver, el módulo dotenv está simulado para el primer caso de prueba y no está simulado para el segundo caso de prueba.

Puedes encontrar la demostración completa aquí: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/56446543

Artículos relacionados