¿Cómo puedo simular una importación de módulo ES6 usando Jest?


Estoy empezando a pensar que esto no es posible, pero quiero preguntar de todos modos.

Quiero probar que uno de mis módulos ES6 llama a otro módulo ES6 de una manera particular. Con Jasmine esto es súper fácil {

El código de la aplicación:

// myModule.js
import dependency from './dependency';

export default (x) => {
  dependency.doSomething(x * 2);
}

Y el código de prueba:

//myModule-test.js
import myModule from '../myModule';
import dependency from '../dependency';

describe('myModule', () => {
  it('calls the dependency with double the input', () => {
    spyOn(dependency, 'doSomething');

    myModule(2);

    expect(dependency.doSomething).toHaveBeenCalledWith(4);
  });
});

¿Cuál es el equivalente con Broma? Siento que esto es una cosa tan simple de querer hacer, pero me he estado arrancando el pelo tratando de averiguarlo.

Lo más cerca que he llegado es mediante la sustitución de la imports con require s, y moviéndolos dentro de las pruebas/funciones. Ninguna de las cuales son cosas que quiero hacer.

// myModule.js
export default (x) => {
  const dependency = require('./dependency'); // yuck
  dependency.doSomething(x * 2);
}

//myModule-test.js
describe('myModule', () => {
  it('calls the dependency with double the input', () => {
    jest.mock('../dependency');

    myModule(2);

    const dependency = require('../dependency'); // also yuck
    expect(dependency.doSomething).toBeCalledWith(4);
  });
});

Para los puntos de bonificación, me encantaría hacer que todo funcione cuando la función dentro de dependency.js es una exportación predeterminada. Sin embargo, sé que espiar las exportaciones predeterminadas no funciona en Jasmine (o al menos nunca podría hacerlo funcionar), por lo que tampoco tengo la esperanza de que sea posible en Broma.

Author: Cam Jackson, 2016-11-07

4 answers

He sido capaz de resolver esto mediante el uso de un truco que implica import *. Incluso funciona tanto para las exportaciones con nombre y por defecto!

Para una exportación con nombre:

// dependency.js
export const doSomething = (y) => console.log(y)

// myModule.js
import { doSomething } from './dependency';

export default (x) => {
  doSomething(x * 2);
}

// myModule-test.js
import myModule from '../myModule';
import * as dependency from '../dependency';

describe('myModule', () => {
  it('calls the dependency with double the input', () => {
    dependency.doSomething = jest.fn(); // Mutate the named export

    myModule(2);

    expect(dependency.doSomething).toBeCalledWith(4);
  });
});

O para una exportación predeterminada:

// dependency.js
export default (y) => console.log(y)

// myModule.js
import dependency from './dependency'; // Note lack of curlies

export default (x) => {
  dependency(x * 2);
}

// myModule-test.js
import myModule from '../myModule';
import * as dependency from '../dependency';

describe('myModule', () => {
  it('calls the dependency with double the input', () => {
    dependency.default = jest.fn(); // Mutate the default export

    myModule(2);

    expect(dependency.default).toBeCalledWith(4); // Assert against the default
  });
});

Como Mihai Damian bien señaló a continuación, esto está mutando el objeto módulo de dependency, y por lo tanto se 'filtrará' a través de otras pruebas. Por lo tanto, si utiliza este enfoque, debe almacenar el valor original y luego volver a configurarlo después de cada prueba. Para hacer esto fácilmente con Jest, utilice spyOn() método en lugar de jest.fn() porque soporta fácilmente la restauración de su valor original, por lo tanto evitando antes mencionado 'fugas'.

 128
Author: Cam Jackson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-05 14:40:01

Tienes que burlarte del módulo y configurar el espía por ti mismo:

import myModule from '../myModule';
import dependency from '../dependency';
jest.mock('../dependency', () => ({
  doSomething: jest.fn()
}))

describe('myModule', () => {
  it('calls the dependency with double the input', () => {
    myModule(2);
    expect(dependency.doSomething).toBeCalledWith(4);
  });
});
 82
Author: Andreas Köberle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-08 07:31:22

Añadiendo más a la respuesta de Andreas. Tuve el mismo problema con el código ES6, pero no quería mutar las importaciones. Eso parecía hacky. Así que hice esto

import myModule from '../myModule';
import dependency from '../dependency';
jest.mock('../dependency');

describe('myModule', () => {
  it('calls the dependency with double the input', () => {
    myModule(2);
  });
});

Y se agregó dependencia.js en "_ _ se burla de la carpeta _ _ " paralela a la dependencia.js. Esto funcionó para mí. Además, esto me dio la opción de devolver los datos adecuados de la implementación simulada. Asegúrese de dar la ruta correcta al módulo que desea burlarse.

 30
Author: mdsAyubi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-19 19:55:28

Para simular una exportación predeterminada del módulo de dependencia ES6 usando jest:

import myModule from '../myModule';
import dependency from '../dependency';

jest.mock('../dependency');

// If necessary, you can place a mock implementation like this:
dependency.mockImplementation(() => 42);

describe('myModule', () => {
  it('calls the dependency once with double the input', () => {
    myModule(2);

    expect(dependency).toHaveBeenCalledTimes(1);
    expect(dependency).toHaveBeenCalledWith(4);
  });
});

Las otras opciones no funcionaron para mi caso.

 25
Author: falsarella,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-11 19:52:08