【发布时间】:2018-05-04 06:17:13
【问题描述】:
模拟 ES6 类导入
我想在我的测试文件中模拟我的 ES6 类导入。
如果被模拟的类有多个消费者,将模拟移动到 __mocks__ 可能是有意义的,这样所有测试都可以共享模拟,但在此之前我想将模拟保留在测试文件中。
Jest.mock()
jest.mock() 可以模拟导入的模块。传递单个参数时:
jest.mock('./my-class.js');
它使用与模拟文件相邻的 __mocks__ 文件夹中的模拟实现,或创建一个自动模拟。
模块出厂参数
jest.mock() 接受一个第二个参数,它是一个模块工厂 函数。 对于使用export default 导出的 ES6 类,不清楚这个工厂函数应该返回什么。是:
- 另一个返回模拟类实例的对象的函数?
- 模仿类实例的对象?
- 具有属性
default的对象是一个返回模拟类实例的对象的函数? - 返回高阶函数的函数,该高阶函数本身返回 1、2 或 3?
The docs 很模糊:
第二个参数可用于指定正在运行的显式模块工厂,而不是使用 Jest 的自动模拟功能:
当消费者imports 类时,我正在努力想出一个可以作为构造函数的工厂定义。我不断收到TypeError: _soundPlayer2.default is not a constructor(例如)。
我尝试避免使用箭头函数(因为它们不能用new 调用)并让工厂返回一个具有default 属性的对象(或没有)。
这是一个例子。这是行不通的;所有测试都抛出TypeError: _soundPlayer2.default is not a constructor。
正在测试的类: sound-player-consumer.js
import SoundPlayer from './sound-player'; // Default import
export default class SoundPlayerConsumer {
constructor() {
this.soundPlayer = new SoundPlayer(); //TypeError: _soundPlayer2.default is not a constructor
}
playSomethingCool() {
const coolSoundFileName = 'song.mp3';
this.soundPlayer.playSoundFile(coolSoundFileName);
}
}
类被嘲笑: sound-player.js
export default class SoundPlayer {
constructor() {
// Stub
this.whatever = 'whatever';
}
playSoundFile(fileName) {
// Stub
console.log('Playing sound file ' + fileName);
}
}
测试文件:sound-player-consumer.test.js
import SoundPlayerConsumer from './sound-player-consumer';
import SoundPlayer from './sound-player';
// What can I pass as the second arg here that will
// allow all of the tests below to pass?
jest.mock('./sound-player', function() {
return {
default: function() {
return {
playSoundFile: jest.fn()
};
}
};
});
it('The consumer should be able to call new() on SoundPlayer', () => {
const soundPlayerConsumer = new SoundPlayerConsumer();
expect(soundPlayerConsumer).toBeTruthy(); // Constructor ran with no errors
});
it('We can check if the consumer called the mocked class constructor', () => {
const soundPlayerConsumer = new SoundPlayerConsumer();
expect(SoundPlayer).toHaveBeenCalled();
});
it('We can check if the consumer called a method on the class instance', () => {
const soundPlayerConsumer = new SoundPlayerConsumer();
const coolSoundFileName = 'song.mp3';
soundPlayerConsumer.playSomethingCool();
expect(SoundPlayer.playSoundFile).toHaveBeenCalledWith(coolSoundFileName);
});
我可以将什么作为第二个参数传递给 jest.mock() 以允许示例中的所有测试通过?如果需要修改测试也没关系 - 只要它们仍然测试相同的东西。
【问题讨论】:
标签: javascript ecmascript-6 jestjs