React 16 Jest ES6 Class Mocks(使用ES6語法類的模擬) 實例3、四

轉載地址react

React 16 Jest ES6 Class Mocks(使用ES6語法類的模擬) 實例3、四

項目初始化

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語法的類。webpack

ES6語法的類是具備一些語法糖的構造函數。所以,ES6語法的類的任何模擬都必須是函數或實際的ES6語法的類(這也是另外一個函數)。
因此可使用模擬函數來模擬它們。以下git

ES6語法類的實例

這裏的實例我使用官方的例子,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();
  }
}

ES6語法的類測試實例三 - 使用模塊工廠參數調用jest.mock()(Calling jest.mock() with the module factory parameter)jest.mock(path,moduleFactory)接受模塊工廠參數。

模塊工廠是一個返回模擬的函數。
爲了模擬構造函數,模塊工廠必須返回構造函數。
換句話說,模塊工廠必須是返回函數的函數 - 高階函數(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"開頭的變量進行例外處理。測試

ES6語法的類測試實例四 - 使用mockImplementation()或mockImplementationOnce()替換mock(Replacing the mock using mockImplementation() or mockImplementationOnce())您能夠經過在現有模擬上

調用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
相關文章
相關標籤/搜索