如果已发送 thunk 动作创建者中的 thunk 动作,我如何检查笑话测试?

How can I check in a jest test if a thunk action within a thunk action creator has been dispatched?

这是一个通用的例子:

// myActions.js
export const actionOne = () => (dispatch) => {
    dispatch(actionTwo());
};

export const actionTwo = () => ({
    type: 'SOME_TYPE',
});

我想测试 actionTwo 是否已被调用或调度,最好是测试不知道 actionTwo 中发生的事情,因为我有一个不同的测试

我正在使用 redux-mock-store 将测试的操作分派到模拟存储并调用 store.getActions() 以查明是否已分派 thunk 操作创建者中的预期操作。我觉得在这种特定情况下这不是正确的方法,因为这样测试会测试得比它应该测试的更多。我真的只想知道 actionTwo 是否被调用过。

我知道 spyOnjest.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' }]);
    }); 
});

非常感谢您的任何建议!

最好断言两个 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');
    });
});

花了我一段时间,但我想通了。这不是理想的(因为它涉及对测试代码的小改动),但最接近我能得到的理想。

// 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;

就是这样。现在我可以确保忽略导出函数的所有副作用并将其作为实际单元进行测试。