轉(zhuǎn)載地址
React 16 Jest ES6 Class Mocks(使用ES6語法類的模擬) 實例三、四
項目初始化
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
ES6 Class Mocks(使用ES6語法類的模擬)
Jest可用于模擬導入到要測試的文件中的ES6語法的類。
ES6語法的類是具有一些語法糖的構(gòu)造函數(shù)。因此,ES6語法的類的任何模擬都必須是函數(shù)或?qū)嶋H的ES6語法的類(這也是另一個函數(shù))。
所以可以使用模擬函數(shù)來模擬它們。如下
ES6語法類的實例
這里的實例我使用官方的例子,SoundPlayer類和SoundPlayerConsumer消費者類。下面部分文件的內(nèi)容參考上篇文章React 16 Jest ES6 Class Mocks(使用ES6語法類的模擬)src/lib/sound-player.js
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.js
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();
}
}
ES6語法的類測試實例三 - 使用模塊工廠參數(shù)調(diào)用jest.mock()(Calling jest.mock() with the module factory parameter)jest.mock(path,moduleFactory)接受模塊工廠參數(shù)。
模塊工廠是一個返回模擬的函數(shù)。
為了模擬構(gòu)造函數(shù),模塊工廠必須返回構(gòu)造函數(shù)。
換句話說,模塊工廠必須是返回函數(shù)的函數(shù) - 高階函數(shù)(HOF)。測試用例如下
src/tests/jest_sound_player_3.test.js
import SoundPlayer from '../lib/sound-player';
import SoundPlayerConsumer from '../lib/sound-player-consumer';
jest.mock('../lib/sound-player'); // SoundPlayer 現(xiàn)在是一個模擬構(gòu)造函數(shù)
const mockPlaySoundFile = jest.fn();
const mockChoicePlaySoundFile = jest.fn();
jest.mock('../lib/sound-player', () => jest.fn().mockImplementation(() => ({
choicePlaySoundFile: mockChoicePlaySoundFile,
playSoundFile: mockPlaySoundFile,
})));
beforeEach(() => {
// 清除所有實例并調(diào)用構(gòu)造函數(shù)和所有方法:
SoundPlayer.mockClear();
mockChoicePlaySoundFile.mockClear();
});
it('我們可以檢查SoundPlayerConsumer是否調(diào)用了類構(gòu)造函數(shù)', () => {
const soundPlayerConsumer = new SoundPlayerConsumer();
expect(SoundPlayer).toHaveBeenCalledTimes(1);
});
it('我們可以檢查SoundPlayerConsumer是否在類實例上調(diào)用了一個方法', () => {
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,
})));
工廠參數(shù)的限制是,由于對jest.mock()的調(diào)用被提升到文件的頂部,因此無法首先定義變量然后在工廠中使用它。
對以"mock"開頭的變量進行例外處理。
ES6語法的類測試實例四 - 使用mockImplementation()或mockImplementationOnce()替換mock(Replacing the mock using mockImplementation() or mockImplementationOnce())您可以通過在現(xiàn)有模擬上
調(diào)用mockImplementation()來替換前面所有的模擬,以便更改單個測試或所有測試的實現(xiàn)。
對jest.mock的調(diào)用被提升到代碼的頂部。
也可以指定模擬,例如在beforeAll()中,通過在現(xiàn)有mock上調(diào)用mockImplementation()或mockImplementationOnce()而不是使用factory參數(shù)。
如果需要,這還允許在測試之間更改模擬:測試用例如下
import SoundPlayer from '../lib/sound-player';
import SoundPlayerConsumer from '../lib/sound-player-consumer';
jest.mock('../lib/sound-player'); // SoundPlayer 現(xiàn)在是一個模擬構(gòu)造函數(shù)
describe('SoundPlayer被調(diào)用的時候拋出異常', () => {
beforeAll(() => {
SoundPlayer.mockImplementation(() => ({
playSoundFile: () => {
throw new Error('Test error');
},
choicePlaySoundFile: () => {
throw new Error('Test error');
},
}));
});
it('play被調(diào)用的收拋出異常', () => {
const soundPlayerConsumer = new SoundPlayerConsumer();
expect(() => soundPlayerConsumer.play()).toThrow();
});
});
上面的代碼注意這里
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