web-dev-qa-db-fra.com

Jest: Mock ES6 Module avec exportation par défaut et nommée

J'ai un module ES6 avec une exportation par défaut et une exportation nommée:

/** /src/dependency.js **/

export function utilityFunction() { return false; }

export default function mainFunction() { return 'foo'; }

Son utilisation par un second module ES6:

/** /src/myModule.js **/

import mainFunction, { utilityFunction } from './dependency';

// EDIT: Fixed syntax error in code sample
// export default myModule() {
export default function myModule() {
    if (!utilityFunction()) return 2;
    return mainFunction();
}

J'essaie d'écrire un test unitaire pour myModule.js à l'aide de Jest. Mais lorsque j'essaie de simuler l'import nommé et l'import par défaut, Jest semble ne simuler que l'import nommé. Il continue à utiliser l'implémentation réelle de l'import par défaut et ne me permet pas de le moquer, même après avoir appelé .mockImplementation (). Voici le code que j'essaie d'utiliser:

/** 
  * Trying to mock both named and default import. 
  * THIS DOESN'T WORK.
  */

/** /tests/myModule.test.js **/

import mainFunction, { utilityFunction } from '../src/dependency';
import myModule from '../src/myModule';

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

mainFunction.mockImplementation(() => 1);
utilityFunction.mockImplementation(() => true);

describe('myModule', () => {
    it('should return the return value of mainFunction when the result of utilityFunction is true', () => {
        expect(myModule()).toEqual(1); // FAILS - actual result is 'foo'
    });
});

Ce comportement me semble vraiment étrange, car lorsque vous vous moquez des importations JUST par défaut ou des importations JUST nommées, cette API fonctionne correctement. Par exemple, dans le cas où myModule.js importe uniquement une importation par défaut, cela se fait assez facilement:

/**
  * Trying to mock just the default import. 
  * THIS WORKS.
  */

/** /src/myModule.js **/

import mainFunction from './dependency';

// EDIT: Fixed syntax error in code sample
// export default myModule() {
export default function myModule() {
    return mainFunction();
}


/** /tests/myModule.test.js **/
// If only mainFunction is used by myModule.js

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

jest.mock('../src/dependency');
mainFunction.mockImplementation(() => 1);

describe('myModule', () => {
    it('should return the return value of mainFunction', () => {
        expect(myModule()).toEqual(1); // Passes
    });
});

Dans le cas où seule l'exportation "utilityFunction" nommée est utilisée, il est également assez facile de simuler l'importation:

/**
  * Trying to mock both named and default import. 
  * THIS WORKS.
  */
/** /src/myModule.js **/

import { utililtyFunction } from './dependency';

// EDIT: Fixed syntax error in code sample
// export default myModule()
export default function myModule() {
    return utilityFunction();
}


/** /tests/myModule.test.js **/
// If only utilityFunction is used by myModule.js

import { utilityFunction } from '../src/dependency';
import myModule from '../src/myModule';

jest.mock('../src/dependency);
utilityFunction.mockImplementation(() => 'bar');

describe('myModule', () => {
    it('should return the return value of utilityFunction', () => {
        expect(myModule()).toEqual('bar'); // Passes
    });
});

Est-il possible de simuler l'import nommé et l'import par défaut en utilisant Jest? Existe-t-il une syntaxe différente que je peux utiliser pour obtenir le résultat souhaité, selon lequel j'importe les valeurs nommées et par défaut d'un module et suis capable de les imiter?

8
bean

Vous avez une erreur de syntaxe ... le mot clé function est omis de l'exportation par défaut dans myModule.js. Devrait ressembler à ceci:

import mainFunction, { utilityFunction } from './dependency';

export default function myModule() {
    if (!utilityFunction()) return 2;
    return mainFunction();
}

Je ne sais pas comment vous avez pu faire le test autrement, mais je viens de l'essayer localement et ça a réussi.

1
djfdev

L'autre solution n'a pas fonctionné pour moi. Voici comment j'ai fait: 

  jest.mock('../src/dependency', () => ({
    __esModule: true,
    utilityFunction: 'utilityFunction',
    default: 'mainFunction'
  }));

Une autre façon de le faire:

jest.unmock('../src/dependency');

const myModule = require('../src/dependency');
myModule.utilityFunction = 'your mock'
5
Albert Olivé