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

30 浏览
0 Comments

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

我想测试我的一个ES6模块是否以特定方式调用另一个ES6模块。使用Jasmine非常容易 -

应用程序代码:

// 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的等效物是什么?我觉得这是一个非常简单的想法,但我一直在试图弄清楚它而感到非常困惑。

我接近的方法是用require代替import,并将它们移动到测试/函数内部。这两件事我都不想做。

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

如果函数在dependency.js内是默认导出,我想获得额外的积分。然而,我知道在Jasmine中不能正确跟踪默认导出(或者至少我从没成功过),所以我不抱希望在Jest中也能实现。

admin 更改状态以发布 2023年5月21日
0
0 Comments

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

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

0
0 Comments

编辑:已经过了几年,这不再是正确的做法了(可能从一开始就不是,我的错)。

对导入的模块进行变异是不好的,可能会导致测试的通过或失败取决于执行顺序等副作用。

为了历史目的,我将保留此答案的原始形式,但你应该真正使用jest.spyOnjest.mock。请参阅jest文档或本页面的其他答案以获取详细信息。

以下是原始答案:


我已经用一个涉及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
  });
});

0