如何使用 browserify 重新加载模块

How can I reload module using browserify

我正在使用 Facebook 的 Dispatcher and Flux Utils React 构建应用 我正在使用 karmamochasinonbrowserify 来测试 Flux商店。这是我的测试片段:

import {expect} from 'chai';
import sinon from 'sinon';

describe('Store', function() {

  let registerSpy, Store, registeredCallback, isDispatchingStub;

  beforeEach(function(done) {
    const Dispatcher = require('../../../dispatcher');
    registerSpy = sinon.spy(Dispatcher, 'register');
    Store = require('../store');
    registeredCallback = registerSpy.lastCall.args[0];
    isDispatchingStub
      = sinon.stub(Dispatcher, "isDispatching", function() { return true; });
    done();
  });

  afterEach(function(done) {
    registerSpy.restore();
    isDispatchingStub.restore();
    done();
  });

  it('should update its state on message', function(done) {
    registeredCallback({
      type: 'MESSAGE',
      payload: {
        message: 'Our message'
      }
    });
    let state = Store.getState();
    expect(state.size).to.equal(1);
    done();
  });

});

如果我只执行一个测试,一切正常。如果我添加另一个测试,我会得到一个错误,因为商店在需要时不会重新加载(我没有得到商店的新副本,它在之前的测试后已经有一些状态)。因此,registerSpy 没有 lastCall 属性 因为调度员已经注册了商店。 Dispatcher也是一样,其他store可以看到dispatched actions,所以不好测试stores。

我试过使用 rewire 但它不支持 browserify。我也试过取消 require.cache 但 Browserify 的 require 没有缓存 属性 像 node 的那样。

如何使用 browserify 获取模块的全新副本?

所以,我尝试了很多东西。 首先,我意识到我不需要浏览器来测试商店,它们不运行 DOM。所以,我使用了删除 require.cache 的解决方案。但是,就像提到的 here 它可能会导致依赖项之间的无限循环等问题。我的测试发生的第一件事是无限循环:)。

This answer 还说您可以将功能包装在一个函数中。

我一直在从像 here 这样的存储文件中导出一个实例。我从商店导出 class 并在测试文件中创建了一个实例。调度员也是一样。所以现在,我在每次测试中都有新的干净存储和调度程序。

商店示例(现在我导出商店 class 和实例):

import {ReduceStore} from 'flux/utils';
import Immutable from 'immutable';
import Dispatcher from '../../dispatcher';

export class AppMessageStore extends ReduceStore {

  getInitialState() {
    return Immutable.List();
  }

  reduce(state, action) {
    switch (action.type) {
      case 'APP_MESSAGE':
        return Immutable.List([action.payload.message]);

      default:
        return state;
    }
  }

}

const instance = new AppMessageStore(Dispatcher);
export default instance;

测试文件(现在我从 flux utils 获得了干净的调度程序。每次测试都会创建一个新的存储,所以每个测试都有自己的存储)。

import {expect} from 'chai';
import sinon from 'sinon';
import {AppMessageStore} from '../index';
import {Dispatcher} from 'flux';

describe.only('AppMessageStore', function() {

  let registerSpy, appMessageStore, registeredCallback, isDispatchingStub;

  beforeEach(function(done) {
    const MyDispatcher = new Dispatcher();
    registerSpy = sinon.spy(MyDispatcher, 'register');
    appMessageStore = new AppMessageStore(MyDispatcher);
    registeredCallback = registerSpy.lastCall.args[0];
    isDispatchingStub
      = sinon.stub(MyDispatcher, "isDispatching", function() { return true; });
    done();
  });

  afterEach(function(done) {
    registerSpy.restore();
    isDispatchingStub.restore();
    done();
  });

  it('should update its state on message', function(done) {
    registeredCallback({
      type: 'APP_MESSAGE',
      payload: {
        message: 'Our message'
      }
    });
    let state = appMessageStore.getState();
    console.log('state.toObject()', state.toObject());
    expect(state.size).to.equal(1);
    done();
  });

  it('should blabla', function(done) {
    registeredCallback({
      type: 'APP_MESSAGE',
      payload: {
        message: 'New message'
      }
    });
    let state = appMessageStore.getState();
    console.log('state.toObject()', state.toObject());
    done();
  });

});