492 votes

Comment puis-je simuler une importation de module ES6 à l'aide de Jest?

Je commence à penser que ce n'est pas possible, mais je veux vous demander de toute façon.

Je veux tester que l'un de mes ES6 modules appelle une autre ES6 module d'une manière particulière. Avec le Jasmin c'est super facile:

Le code de l'application:

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

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

Et le code de test:

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

Ce qui est l'équivalent avec la Blague? J'ai l'impression que c'est une chose toute simple à faire, mais j'ai été déchirant mes cheveux à essayer de comprendre.

Le plus proche que je suis venu, c'est par le remplacement de l' imports avec requires, et en les déplaçant à l'intérieur de l'tests/fonctions. Ni de qui sont des choses que je veux faire.

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

Pour les points de bonus, j'aimerais faire tout fonctionner lorsque la fonction à l'intérieur d' dependency.js est une valeur par défaut à l'exportation. Cependant, je sais que l'espionnage sur les défaut des exportations ne fonctionne pas dans le Jasmin (ou, au moins, je n'ai jamais pu le faire fonctionner), donc je ne suis pas l'espoir qu'il est possible dans la Plaisanterie.

299voto

Cam Jackson Points 1155

J'ai été en mesure de résoudre ce problème en utilisant un hack impliquant import *. Il fonctionne même pour les deux nommés par défaut et les exportations!

Pour une exportation:

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

Ou pour une exportation par défaut:

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

Comme Mihai Damian très justement souligné ci-dessous, c'est la mutation de l'objet module d' dependency, et c'est une "fuite" sur d'autres tests. Donc, si vous utilisez cette approche, vous devez stocker la valeur d'origine puis retournez à nouveau après chaque test. Pour ce faire facilement avec la Plaisanterie, l'utilisation spyOn() méthode au lieu de jest.fn() parce qu'il supporte facilement la restauration de sa valeur d'origine, donc éviter avant mentionné 'fuite'.

287voto

Andreas Köberle Points 16453

Vous devez vous moquer du module et paramétrer l'espion par vous-même:

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

73voto

falsarella Points 2674

Pour simuler une exportation par défaut du module de dépendance ES6 à l'aide de 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);
  });
});
 

Les autres options ne fonctionnaient pas pour mon cas.

42voto

mdsAyubi Points 814

Ajouter plus à la réponse d'Andreas. J'ai eu le même problème avec le code ES6, mais je ne voulais pas muter les importations. Cela avait l'air hacky. Alors j'ai fait ça

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

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

Et ajouté dependency.js dans le dossier "__ mocks __" parallèlement à dependency.js. Cela a fonctionné pour moi. En outre, cela m'a donné la possibilité de renvoyer des données appropriées de la mise en œuvre fictive. Assurez-vous de donner le bon chemin au module que vous voulez simuler.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X