测试附加时间戳的 Redux action creator

Testing a Redux action creator that appends a timestamp

针对动作创建者编写 Mocha 测试规范时,我如何确定时间戳是在动作创建者中生成的?

它不一定要使用 Sinon,但我尝试使用 Sinon Fake Timers 到 "freeze time",但由于我有限的存根知识,似乎无法将其拼凑起来和嘲笑。如果这被认为是 Redux 反模式,请指出我更好的方向,但我的理解是 Redux 动作创建者可以是非纯函数,与 reducers 不同。

Redux Writing Tests Recipes这里借用一点是我理解的问题的核心...

CommonUtils.js

import moment from 'moment';

export const getTimestamp = function () {
  return moment().format();
};

TodoActions.js

import { getTimestamp } from '../../utils/CommonUtils';    

export function addTodo(text) {
  return {
    type: 'ADD_TODO',
    text,
    timestamp: getTimestamp() // <-- This is the new property
  };
};

TodoActions.spec.js

import expect from 'expect';
import * as actions from '../../actions/TodoActions';
import * as types from '../../constants/ActionTypes';
import { getTimestamp } from '../../utils/CommonUtils';

describe('actions', () => {
  it('should create an action to add a todo', () => {
    const text = 'Finish docs';
    const timestamp = getTimestamp(); // <-- This will often be off by a few milliseconds
    const expectedAction = {
      type: types.ADD_TODO,
      text,
      timestamp
    };
    expect(actions.addTodo(text)).toEqual(expectedAction);
  });
});

我仍然很想看到其他答案,但我终于找到了一个合理的解决方案。此答案使用 proxyquire 到 override/replace getTimestamp() 中定义的方法 CommonUtils 使用时测试期间的 TodoActions

没有对上面的 CommonUtils.jsTodoActions.js 进行修改:

TodoActions.spec.js

import expect from 'expect';
import proxyquire from 'proxyquire';
import * as types from '../../constants/ActionTypes';

const now = '2016-01-06T15:30:00-05:00';
const commonStub = {'getTimestamp': () => now};
const actions = proxyquire('../../actions/TodoActions', {
    '../../utils/CommonUtils': commonStub
});

describe('actions', () => {
  it('should create an action to add a todo', () => {
    const text = 'Finish docs';
    const timestamp = now; // <-- Use the variable defined above
    const expectedAction = {
      type: types.ADD_TODO,
      text,
      timestamp
    };
    expect(actions.addTodo(text)).toEqual(expectedAction);
  });
});

在测试的时候我曾经成功地使用过这个库:https://www.npmjs.com/package/timekeeper

然后在 beforeEach 和 afterEach 中,您可以将时间保存为特定的内容并进行断言,然后将时间重置为正常。

  let time;
  beforeEach(() => {
    time = new Date(1451935054510); // 1/4/16
    tk.freeze(time);
  });

  afterEach(() => {
    tk.reset();
  });

现在您可以断言返回的时间。这有意义吗?