运行 单元测试时,异步动作创建者中的 .forEach 不返回动作
.forEach within async action creator not returning action when running unit test
我正在使用 react/redux 生成一个面板列表,每个面板都显示每个列表项的数据。我设置了一个 5 秒的时间间隔来调用 refreshAppList(this.props.list) 动作创建器,forEach 循环遍历列表中的每个项目并进行异步调用,然后分派刷新的列表项(使用 redux-thunk)。所以基本上,我每 5 秒刷新一次包含最新数据的面板列表。这很好用!不幸的是,现在我正在为这个特定的异步动作创建者编写单元测试,我遇到了 运行 问题。 .forEach 没有 return 任何东西,所以当我在我的单元测试中调用它时,我变得不确定。有谁知道如何解决这个问题,或者我可能需要使用不同的方法来刷新整个面板列表?
这是遍历数组并对每个数组项进行异步调用的动作创建者。
export const refreshAppList = list => (dispatch) => {
list.forEach((version, index) => {
const url = `apiEndpoint/${version.data.app_id}/${version.data.version}`;
return axios.get(url)
.then(({ data }) => {
data.uniqueId = version.uniqueId;
data.refreshId = uuidv1();
dispatch({ type: REFRESH_APP_LIST, payload: { index, data } });
})
.catch((e) => {
console.log(e);
});
});
};
这是我收到的错误:
1) async actions creates an action with type: REFRESH_APP_LIST:
TypeError: Cannot read property 'then' of undefined
at Context.<anonymous> (tests/asyncActions.js:140:12)
这是我在测试中调用动作创建器的地方(使用 redux-mock-store):
return store.dispatch(refreshAppList(list)).then(() => {
expect(store.getActions()).to.deep.equal(expectedActions);
});
我认为还值得一提的是,我正在使用 axios-mock-adapter 来模拟数据 return 从 action creator 中的异步调用编辑的数据。
最后一件事:我在同一个应用程序中为另外两个异步操作创建者编写了单元测试并且都通过了。最大的区别是这个特定的动作创建者使用 forEach 循环将多个异步调用链接在一起(这不是 return 对测试进行任何测试)。
那是行不通的,因为 refreshAppList
return 的函数没有 return 任何东西。此外,即使您从内部执行 return axios.get.
,.forEach
也不会 return 任何内容。您可以使用 .map
代替 return Promise.all
中的所有内容。像这样
export const refreshAppList = list => (dispatch) => {
return Promise.all(list.map((version, index) => {
const url = `apiEndpoint/${version.data.app_id}/${version.data.version}`;
return axios.get(url)
.then(({ data }) => {
data.uniqueId = version.uniqueId;
data.refreshId = uuidv1();
dispatch({ type: REFRESH_APP_LIST, payload: { index, data } });
})
.catch((e) => {
console.log(e);
});
}));
};
我正在使用 react/redux 生成一个面板列表,每个面板都显示每个列表项的数据。我设置了一个 5 秒的时间间隔来调用 refreshAppList(this.props.list) 动作创建器,forEach 循环遍历列表中的每个项目并进行异步调用,然后分派刷新的列表项(使用 redux-thunk)。所以基本上,我每 5 秒刷新一次包含最新数据的面板列表。这很好用!不幸的是,现在我正在为这个特定的异步动作创建者编写单元测试,我遇到了 运行 问题。 .forEach 没有 return 任何东西,所以当我在我的单元测试中调用它时,我变得不确定。有谁知道如何解决这个问题,或者我可能需要使用不同的方法来刷新整个面板列表?
这是遍历数组并对每个数组项进行异步调用的动作创建者。
export const refreshAppList = list => (dispatch) => {
list.forEach((version, index) => {
const url = `apiEndpoint/${version.data.app_id}/${version.data.version}`;
return axios.get(url)
.then(({ data }) => {
data.uniqueId = version.uniqueId;
data.refreshId = uuidv1();
dispatch({ type: REFRESH_APP_LIST, payload: { index, data } });
})
.catch((e) => {
console.log(e);
});
});
};
这是我收到的错误:
1) async actions creates an action with type: REFRESH_APP_LIST:
TypeError: Cannot read property 'then' of undefined
at Context.<anonymous> (tests/asyncActions.js:140:12)
这是我在测试中调用动作创建器的地方(使用 redux-mock-store):
return store.dispatch(refreshAppList(list)).then(() => {
expect(store.getActions()).to.deep.equal(expectedActions);
});
我认为还值得一提的是,我正在使用 axios-mock-adapter 来模拟数据 return 从 action creator 中的异步调用编辑的数据。
最后一件事:我在同一个应用程序中为另外两个异步操作创建者编写了单元测试并且都通过了。最大的区别是这个特定的动作创建者使用 forEach 循环将多个异步调用链接在一起(这不是 return 对测试进行任何测试)。
那是行不通的,因为 refreshAppList
return 的函数没有 return 任何东西。此外,即使您从内部执行 return axios.get.
,.forEach
也不会 return 任何内容。您可以使用 .map
代替 return Promise.all
中的所有内容。像这样
export const refreshAppList = list => (dispatch) => {
return Promise.all(list.map((version, index) => {
const url = `apiEndpoint/${version.data.app_id}/${version.data.version}`;
return axios.get(url)
.then(({ data }) => {
data.uniqueId = version.uniqueId;
data.refreshId = uuidv1();
dispatch({ type: REFRESH_APP_LIST, payload: { index, data } });
})
.catch((e) => {
console.log(e);
});
}));
};