如何使用 Jest 模拟 ES6 模块导入?

我想测试我的一个ES6模块以特定的方式调用另一个ES6模块。有了茉莉花,这超级容易——

应用程序代码:

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

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

和测试代码:

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

与Jest的等价物是什么?我觉得这是一件很简单的事情,但我一直在撕扯我的头发试图弄清楚它。

我最接近的是用s替换s,并将它们移动到测试/函数中。这两件事都不是我想做的。importrequire

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

对于奖励积分,当里面的函数是默认导出时,我很乐意让整个事情工作。但是,我知道监视默认导出在Jasmine中不起作用(或者至少我永远无法让它工作),所以我也不抱有希望在Jest中实现它。dependency.js


答案 1

编辑:几年过去了,这不再是这样做的正确方法(可能从来都不是,我的坏)。

更改导入的模块是令人讨厌的,并且可能导致副作用,例如测试根据执行顺序通过或失败。

出于历史目的,我将这个答案以原始形式保留,但你真的应该使用jest.spyOnjest.mock。有关详细信息,请参阅此页面上的开玩笑文档或其他答案。

原始答案如下:


我已经能够通过使用涉及.它甚至适用于命名和默认导出!import *

对于命名导出:

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

或者对于默认导出:

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


答案 2

您必须模拟模块并自己设置间谍:

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