转载地址react
git clone https://github.com/durban89/webpack4-react16-reactrouter-demo.git cd webpack4-react16-reactrouter-demo git fetch origin git checkout v_1.0.31 npm install
Jest可用于模拟导入到要测试的文件中的ES6语法的类。webpack
ES6语法的类是具备一些语法糖的构造函数。所以,ES6语法的类的任何模拟都必须是函数或实际的ES6语法的类(这也是另外一个函数)。
因此可使用模拟函数来模拟它们。以下git
这里的实例我使用官方的例子,SoundPlayer类和SoundPlayerConsumer消费者类。下面部分文件的内容参考上篇文章React 16 Jest ES6 Class Mocks(使用ES6语法类的模拟)src/lib/sound-player.jsgithub
export default class SoundPlayer { constructor() { this.name = 'Player1'; this.fileName = ''; } choicePlaySoundFile(fileName) { this.fileName = fileName; } playSoundFile() { console.log('播放的文件是:', this.fileName); } }
src/lib/sound-player-consumer.jsweb
import SoundPlayer from './sound-player'; export default class SoundPlayerConsumer { constructor() { this.soundPlayer = new SoundPlayer(); } play() { const coolSoundFileName = 'song.mp3'; this.soundPlayer.choicePlaySoundFile(coolSoundFileName); this.soundPlayer.playSoundFile(); } }
模块工厂是一个返回模拟的函数。
为了模拟构造函数,模块工厂必须返回构造函数。
换句话说,模块工厂必须是返回函数的函数 - 高阶函数(HOF)。测试用例以下
src/__tests__/jest_sound_player_3.test.jsnpm
import SoundPlayer from '../lib/sound-player'; import SoundPlayerConsumer from '../lib/sound-player-consumer'; jest.mock('../lib/sound-player'); // SoundPlayer 如今是一个模拟构造函数 const mockPlaySoundFile = jest.fn(); const mockChoicePlaySoundFile = jest.fn(); jest.mock('../lib/sound-player', () => jest.fn().mockImplementation(() => ({ choicePlaySoundFile: mockChoicePlaySoundFile, playSoundFile: mockPlaySoundFile, }))); beforeEach(() => { // 清除全部实例并调用构造函数和全部方法: SoundPlayer.mockClear(); mockChoicePlaySoundFile.mockClear(); }); it('咱们能够检查SoundPlayerConsumer是否调用了类构造函数', () => { const soundPlayerConsumer = new SoundPlayerConsumer(); expect(SoundPlayer).toHaveBeenCalledTimes(1); }); it('咱们能够检查SoundPlayerConsumer是否在类实例上调用了一个方法', () => { const soundPlayerConsumer = new SoundPlayerConsumer(); const coolSoundFileName = 'song.mp3'; soundPlayerConsumer.play(); expect(mockChoicePlaySoundFile).toHaveBeenCalledWith(coolSoundFileName); });
注意上面代码中的这段代码函数
const mockPlaySoundFile = jest.fn(); const mockChoicePlaySoundFile = jest.fn(); jest.mock('../lib/sound-player', () => jest.fn().mockImplementation(() => ({ choicePlaySoundFile: mockChoicePlaySoundFile, playSoundFile: mockPlaySoundFile, })));
工厂参数的限制是,因为对jest.mock()的调用被提高到文件的顶部,所以没法首先定义变量而后在工厂中使用它。
对以"mock"开头的变量进行例外处理。测试
调用mockImplementation()来替换前面全部的模拟,以便更改单个测试或全部测试的实现。
对jest.mock的调用被提高到代码的顶部。
也能够指定模拟,例如在beforeAll()中,经过在现有mock上调用mockImplementation()或mockImplementationOnce()而不是使用factory参数。
若是须要,这还容许在测试之间更改模拟:测试用例以下fetch
import SoundPlayer from '../lib/sound-player'; import SoundPlayerConsumer from '../lib/sound-player-consumer'; jest.mock('../lib/sound-player'); // SoundPlayer 如今是一个模拟构造函数 describe('SoundPlayer被调用的时候抛出异常', () => { beforeAll(() => { SoundPlayer.mockImplementation(() => ({ playSoundFile: () => { throw new Error('Test error'); }, choicePlaySoundFile: () => { throw new Error('Test error'); }, })); }); it('play被调用的收抛出异常', () => { const soundPlayerConsumer = new SoundPlayerConsumer(); expect(() => soundPlayerConsumer.play()).toThrow(); }); });
上面的代码注意这里this
beforeAll(() => { SoundPlayer.mockImplementation(() => ({ playSoundFile: () => { throw new Error('Test error'); }, choicePlaySoundFile: () => { throw new Error('Test error'); }, })); });
实践项目地址
git clone https://github.com/durban89/webpack4-react16-reactrouter-demo.git git checkout v_1.0.32