Jest: Mock ES6 Module с экспортом по умолчанию и именованным экспортом

У меня есть модуль ES6 как с экспортом по умолчанию, так и с именованным экспортом:

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

export function utilityFunction() { return false; }

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

Его использует второй модуль 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();
}

Я пытаюсь написать модульный тест для myModule.js с помощью Jest. Но когда я пытаюсь имитировать как именованный импорт, так и импорт по умолчанию, Jest, похоже, имитирует только именованный импорт. Он продолжает использовать фактическую реализацию импорта по умолчанию и не позволяет мне издеваться над ним даже после того, как я вызываю .mockImplementation (). Вот код, который я пытаюсь использовать:

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

Такое поведение кажется мне действительно странным, потому что при насмешке ТОЛЬКО импорта по умолчанию или ТОЛЬКО именованного импорта этот API работает нормально. Например, в случае, когда myModule.js импортирует только импорт по умолчанию, это довольно легко сделать:

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

В случае, когда используется только экспорт с именем 'utilityFunction', также довольно легко имитировать импорт:

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

Можно ли с помощью Jest смоделировать именованный импорт и импорт по умолчанию? Есть ли другой синтаксис, который я могу использовать для достижения желаемого результата, когда я импортирую как именованные, так и значения по умолчанию из модуля и могу издеваться над ними обоими?


person bean    schedule 14.02.2018    source источник
comment
Привет, Вы пробовали мой ответ? Я думаю, это то, что вы ищете. Кроме того, если это сработает, не могли бы вы дать лучший ответ?   -  person Albert Olivé    schedule 24.07.2018


Ответы (2)


У вас есть синтаксическая ошибка ... ключевое слово function опущено в экспорте по умолчанию в myModule.js. Должно выглядеть так:

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

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

Я не уверен, как вам удалось запустить тест в противном случае, но я просто попробовал это локально, и он прошел.

person djfdev    schedule 14.02.2018
comment
Привет, djfdev, спасибо за ответ! Оказывается, вы правы, и предоставленный мной пример кода действительно работает в моей среде. То, что я написал в вопросе, оказывается чрезмерным упрощением проблемы, с которой я сталкиваюсь - в моем случае импорта по умолчанию является компонент React. Стоит ли редактировать вопрос, чтобы предоставить фактический код? В противном случае я могу отметить этот вопрос как ответ и открыть новый. - person bean; 15.02.2018
comment
Поразмыслив еще немного, я отмечу ваш ответ как правильный и открою новый вопрос. Спасибо еще раз! - person bean; 15.02.2018
comment
Мой обновленный вопрос здесь: stackoverflow.com/questions/48831701/ - person bean; 16.02.2018

Другое решение у меня не сработало. Вот как я это сделал:

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

Другой способ сделать это:

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

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