在 ES6 中使用 Jest 测试 React Flux Store

Posted

技术标签:

【中文标题】在 ES6 中使用 Jest 测试 React Flux Store【英文标题】:Testing React Flux Store with Jest in ES6 【发布时间】:2017-01-12 06:46:29 【问题描述】:

我正在尝试使用 Jest 和 ES6 类测试我的 React 存储。我想知道如何在每次测试之前“重置”测试存储或获取新实例。

我的商店包含:

import BaseStore from './BaseStore';
import  MIDI_PLUGIN_LOADED  from '../constants/MidiConstants';


class MidiStore extends BaseStore 

  constructor() 
    super();
    this.subscribe(() => this._registerToActions.bind(this));
    this._midiPlayer = null;
  

  _registerToActions(action) 
    switch (action.actionType) 
      case MIDI_PLUGIN_LOADED:
        this._midiPlayer = action.player;
        this.emitChange();
        break;
    
  

  get midiPlayer() 
    return this._midiPlayer;
  


export default new MidiStore();

我的 Jest 测试代码:

import  MIDI_PLUGIN_LOADED  from '../../constants/MidiConstants';
import AppDispatcher from '../../dispatchers/AppDispatcher';
import MidiStore from '../MidiStore';

describe('MidiStore', () => 

  var actionMidiPluginLoaded = 
    actionType: MIDI_PLUGIN_LOADED,
    player: true
  ;

  it('stores global midi plugin', () => 
    AppDispatcher.dispatch(actionMidiPluginLoaded);
    let 
      midiPlayer
     = MidiStore;

    expect(midiPlayer).toBe(true);
  );

  // fails cause midiPlayer = true
  it('should initialize with no player', () => 
    let 
      midiPlayer
     = MidiStore;

    expect(midiPlayer).toBeNull();
  );

);

问题是第二个“it”语句失败,因为MidiStore 在第一次运行后没有重置。

我知道切换两个“it”语句会通过两个测试,但这不是真正的解决方案。

在 ES5 Jest 中,可以在 beforeEach 中调用 var MidiStore = require('../MidiStore); 以在每次运行时获取一个新实例。我如何使用 ES6 来实现这一点?

【问题讨论】:

【参考方案1】:

我自己设法解决了这个问题。通过在玩笑beforeEach 回调中使用“旧”require,可以为每个测试函数获取一个新实例。

import  MIDI_PLUGIN_LOADED  from '../../constants/MidiConstants';

jest.mock('../../dispatchers/AppDispatcher');

describe('MidiStore', () => 

  var AppDispatcher;
  var MidiStore;
  var callback;

  var actionMidiPluginLoaded = 
    actionType: MIDI_PLUGIN_LOADED,
    player: true
  ;

  beforeEach(() => 
    jest.resetModules();
    AppDispatcher = require('../../dispatchers/AppDispatcher').default;
    MidiStore = require('../MidiStore').default;
    callback = AppDispatcher.register.mock.calls[0][0];
  );

  it('registers a callback with the dispatcher', () => 
    expect(AppDispatcher.register.mock.calls.length).toBe(1);
  );

  it('stores global midi plugin', () => 
    callback(actionMidiPluginLoaded);
    expect(MidiStore.midiPlayer).toBe(true);
  );

  it('should initialize with no player', () => 
    expect(MidiStore.midiPlayer).toBeNull();
  );

);

beforeEach 调用中,我使用jest.resetModules(); 重置模块并获取调度程序、存储和注册回调的新实例。注册的回调是从调度程序中检索到的,现在它被 jest 模拟了。对于实现模拟功能(在其他测试中),我参考了https://facebook.github.io/jest/docs/api.html#mockfn-mockimplementation-fn

【讨论】:

以上是关于在 ES6 中使用 Jest 测试 React Flux Store的主要内容,如果未能解决你的问题,请参考以下文章

Jest React 测试 es6 导入/导出不需要的模拟

Jest Manual Mocks with React 和 Typescript:模拟 ES6 类依赖

如何在 React 和 Webpack 中使用 Jest

如何使用Jest在ES6类方法中测试对redux存储的调度?

babel-jest 不处理模块内的 ES6

jest.mock():如何使用工厂参数模拟 ES6 类默认导入