轉載地址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