Redux Mock Store给出“操作必须是普通对象。使用自定义中间件执行异步操作。”

时间:2019-04-22 10:23:20

标签: javascript testing redux jestjs redux-mock-store

我正在尝试使用redux-mock-storeReact应用中测试一些异步代码。

const configureMockStore = require('redux-mock-store').default;
const thunk = require("redux-thunk").default;

const middlewares = [thunk];
const mockStore = configureMockStore(middlewares);

const dummy = () => {
  // Mock Ajax call
  return new Promise((resolve, reject) => {
      setTimeout(() => resolve({data: 'data'}), 200)
  })
};

describe("Redux Mock Store", () => {
  it("Test Dummy Ajax call", () => {
    const expectedActions = [
      { type: "SUCCESS", payload: "success" },
      { type: "FAILURE", error: { Error: "Error" } }
    ];
    const store = mockStore({});

    store.dispatch(dummy().then(() => {
              expect(store.getActions()).toEqual(expectedActions) 
           }).catch(error => { console.log(error) }))
  });
});

我正在使用Jest来运行此测试。在以上测试Actions must be plain objects. Use custom middleware for async actions.上运行时,出现以下错误?

1 个答案:

答案 0 :(得分:0)

问题是您正在使用 redux-thunk 中间件,但是一旦您的诺言得到解决,您就不会调度任何动作(您可以检查如何定义使用 redux-thunk的动作创建者documentation中。

因此,您需要定义一个动作创建者,该动作创建者使用您的 dummy ajax请求并在动作完成后分派一个动作:

const dummy = () => {
    // Mock Ajax call
    // Note that you are not capturing any error in here and you are not
    // calling the reject method, so your *catch* clausule will never be
    // executed.
    return new Promise((resolve, reject) => {
        setTimeout(() => resolve({ data: 'success' }), 200);
    });
};

const actionCreator = () => (dispatch) => {
    return dummy()
        .then(payload => dispatch({ type: 'SUCCESS', payload }))
        .catch(error => dispatch({ type: 'FAILURE', error }));
};

请注意,动作创建者如何接收参数 dispatch (由 redux-thunk 中间件提供),我们使用该函数来分配动作(即简单对象) )。

一旦使用正确的参数调用动作创建者,则应在 it 中返回您的诺言,以便等到诺言得到解决并在 then内执行期望后语句:

describe('Redux Mock Store', () => {
    it('Test Dummy Ajax call', () => {
        const expectedActions = [
            { type: 'SUCCESS', payload: { data: 'success' } },
        ];
        const store = mockStore({});

        return store.dispatch(actionCreator()).then(() => {
            expect(store.getActions()).toEqual(expectedActions);
        });
    });
});

此外,请考虑到在您的初始测试中,您预期将分派两个动作,但是您只调用一次动作创建者。您应该在另一个 it 中测试失败案例。

您可以看到该解决方案在here中起作用。