如果 thunk 动作创建者中的 thunk 动作已被调度,我如何检查一个笑话测试?
Posted
技术标签:
【中文标题】如果 thunk 动作创建者中的 thunk 动作已被调度,我如何检查一个笑话测试?【英文标题】:How can I check in a jest test if a thunk action within a thunk action creator has been dispatched? 【发布时间】:2018-01-04 19:14:59 【问题描述】:这是一个通用的例子:
// myActions.js
export const actionOne = () => (dispatch) =>
dispatch(actionTwo());
;
export const actionTwo = () => (
type: 'SOME_TYPE',
);
我想测试 actionTwo
是否已被调用或分派,理想情况下,测试不知道 actionTwo
中发生了什么,因为我有一个不同的测试来处理这个问题。
我正在使用redux-mock-store
将经过测试的操作分派到模拟商店并调用store.getActions()
以查明是否已分派了thunk 操作创建器中的预期操作。我觉得在这种特殊情况下这不是正确的方法,因为那样测试会比它应该测试的更多。我真的只想知道actionTwo
是否被调用过。
我知道spyOn
和jest.mock
,但我无法使用它们来解决我的问题。这是广义测试的样子:
// myActions.test.js
import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';
import * as actions from 'myActions';
const mockStore = configureMockStore([thunk]);
test('actionOne', () =>
const store = mockStore();
return store.dispatch(actions.actionOne()).then(() =>
// TODO: check if actions.actionTwo was called
);
);
test('actionTwo', () =>
const store = mockStore();
return store.dispatch(actions.actionTwo()).then(() =>
expect(store.getActions()).toEqual([ type: 'SOME_TYPE' ]);
);
);
感谢您的任何建议!
【问题讨论】:
【参考方案1】:花了我一段时间,但我想通了。这并不理想(因为它涉及对测试代码的小改动),但我能得到的最接近理想。
// myActions.js
export const actionOne = () => (dispatch) =>
dispatch(exports.actionTwo());
;
export const actionTwo = () => (
type: 'SOME_TYPE',
);
重要的变化是exports.actionTwo()
。这样,我确保我可以从外部(测试文件)覆盖函数的实现,并且实际上会从导入的文件中调用覆盖函数。
现在我可以简单地将如下内容添加到我的测试文件中:
beforeEach(() =>
actions.actionTwo = jest.fn(() => () => Promise.resolve());
);
actionTwo
现在被嘲笑,我可以使用toBeCalledWith
和其他期望。如果我想在同一个测试文件中测试它的实际实现,我可以在调用beforeEach
之前将它存储在一个变量中,比如:
const actionTwo = actions.actionTwo;
然后在其实现的测试设置中,我可以覆盖模拟调用
actions.actionTwo = actionTwo;
就是这样。现在我可以确保忽略导出函数的所有副作用,并将其作为实际单元进行测试。
【讨论】:
【参考方案2】:最好断言两个 redux 动作 进入商店,而不是 actionOne 调用动作创建者。
因为所有派发到商店的动作都必须有一个动作type
。只需断言store.getActions()
:
test('actionOne', () =>
const store = mockStore();
return store.dispatch(actions.actionOne()).then(() =>
expect(store.getActions()).to.have.length(2);
expect(store.getActions()[0].type).to.equal('ACTION_ONE_TYPE');
// make additional assertions about the first action
expect(store.getActions()[1].type).to.equal('ACTION_TWO_TYPE');
);
);
【讨论】:
感谢您的回复,但我不相信这是正确的方法。想象一下actionTwo
不是一个简单的动作创建者,而是一个 thunk,调度自己的动作,甚至可能有条件地调度。我不想知道actionOne
测试中的任何逻辑,我只想确保actionTwo
完全被调度,甚至只是函数被调用。没有简单的方法可以实现吗?
同意。我不想测试动作的实现(它在别处测试过),我只想测试它是否被调用。以上是关于如果 thunk 动作创建者中的 thunk 动作已被调度,我如何检查一个笑话测试?的主要内容,如果未能解决你的问题,请参考以下文章
Thunk 动作创建者派出另一个 thunk 动作创建者,但 typescript 抛出错误。我应该添加啥类型?
使用 redux-thunk 从 React Native 中的动作创建者返回 Promise