轉載位址
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.29
npm install
ES6 Class Mocks(使用ES6文法類的模拟)
Jest可用于模拟導入到要測試的檔案中的ES6文法的類。
ES6文法的類是具有一些文法糖的構造函數。是以,ES6文法的類的任何模拟都必須是函數或實際的ES6文法的類(這也是另一個函數)。
是以可以使用模拟函數來模拟它們。如下
一個ES6文法類的執行個體
這裡的執行個體我使用官方的例子,SoundPlayer類和SoundPlayerConsumer消費者類。
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文法的類測試,今天先使用第一種方式 - 自動模拟(Automatic mock)
調用jest.mock('../lib/sound-player')會傳回一個有用的“自動模拟”,可以使用它來監視對類構造函數及其所有方法的調用。
它用模拟構造函數替換ES6文法的類,并使用總是傳回undefined的mock函數替換它的所有方法。
方法調用儲存在AutomaticMock.mock.instances [index] .methodName.mock.calls中。
請注意,如果在類中使用箭頭功能,它們将不會成為模拟的一部分。
原因是箭頭函數不存在于對象的原型上,它們隻是包含對函數的引用的屬性。
如果不需要替換類的實作,這是最簡單的設定選項。測試用例如下:
src/__tests__/jest_sound_player.test.js
import SoundPlayer from '../lib/sound-player';
import SoundPlayerConsumer from '../lib/sound-player-consumer';
jest.mock('../lib/sound-player'); // SoundPlayer 現在是一個模拟構造函數
beforeEach(() => {
// 清除所有執行個體并調用構造函數和所有方法:
SoundPlayer.mockClear();
});
it('我們可以檢查SoundPlayerConsumer是否調用了類構造函數', () => {
const soundPlayerConsumer = new SoundPlayerConsumer();
expect(SoundPlayer).toHaveBeenCalledTimes(1);
});
it('我們可以檢查SoundPlayerConsumer是否在類執行個體上調用了一個方法', () => {
// 檢查 mockClear() 會否起作用:
expect(SoundPlayer).not.toHaveBeenCalled();
const soundPlayerConsumer = new SoundPlayerConsumer();
// 類構造函數再次被調用
expect(SoundPlayer).toHaveBeenCalledTimes(1);
const coolSoundFileName = 'song.mp3';
soundPlayerConsumer.play();
// mock.instances可用于自動模拟
const mockSoundPlayerInstance = SoundPlayer.mock.instances[0];
const mockChoicePlaySoundFile = mockSoundPlayerInstance.choicePlaySoundFile;
expect(mockChoicePlaySoundFile.mock.calls[0][0]).toEqual(coolSoundFileName);
// 相當于上面的檢查
expect(mockChoicePlaySoundFile).toHaveBeenCalledWith(coolSoundFileName);
expect(mockChoicePlaySoundFile).toHaveBeenCalledTimes(1);
});
運作會得到類似如下輸出
PASS src/__tests__/jest_sound_player.test.js
我們可以檢查SoundPlayerConsumer是否調用了類構造函數 (4ms)
我們可以檢查SoundPlayerConsumer是否在類執行個體上調用了一個方法 (3ms)
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 2.27s
Ran all test suites matching /src\/__tests__\/jest_sound_player.test.js/i.
下次介紹第二種方法 - 手動模拟(Manual mock)
實踐項目位址
git clone https:// github.com/durban89/webpack4-react16-reactrouter-demo.git
git checkout v_1.0.30