Javascript 我该如何模仿两次回访或一次承诺一次回访?
我正在尝试测试loadAllProjects函数 测试在.then()处失败,错误为:TypeError:无法读取未定义的属性“then” 我还尝试用token()模拟GetHeaders的响应,但无法使其正常工作 我在这一点上打了个台球,非常感谢您的帮助 测试: 代码: 测试中使用的存储:Javascript 我该如何模仿两次回访或一次承诺一次回访?,javascript,reactjs,jestjs,fetch-api,Javascript,Reactjs,Jestjs,Fetch Api,我正在尝试测试loadAllProjects函数 测试在.then()处失败,错误为:TypeError:无法读取未定义的属性“then” 我还尝试用token()模拟GetHeaders的响应,但无法使其正常工作 我在这一点上打了个台球,非常感谢您的帮助 测试: 代码: 测试中使用的存储: const store = mockStore(Map( { allProjects: Map({ }), c
const store = mockStore(Map(
{
allProjects: Map({
}),
currentProject: Map({
authenticationData: Map({
})
})
})
);
您使用什么Redux中间件来实现异步?确保在创建用于测试的存储时设置了中间件 因为我没有看到上面代码中的任何地方,所以我假设我们这里没有使用中间件 由于loadAllProjects是一个高阶函数,我会这样做:
it('should create SET_ALL_PROJECTS action when fetching projects', (done) => {
fetch
.once(JSON.stringify([{ access_token: "12345" }]))
.once(JSON.stringify({ name: "x" }))
const expectedActions = [
{ type: "SET_ALL_PROJECTS", json: { name: "x" } },
]
// Higher order function that returns a new function.
const loadAllProjectsAsync = actions.loadAllProjects();
// The function returned expects a dispatch from Redux as an argument.
// It will do async work and when its done, it will call the provided dispatch.
loadAllProjectsAsync(store.dispatch).then(() => {
expect(store.getActions()).toEqual(expectedActions);
done();
})
});
您还需要修改LoadAllProject的代码,以便内部函数返回承诺:
export const loadAllProjects = () => {
return (dispatch) => {
// You will need to return the promise in order for the test to be able to call .then() on it.
return getHeadersWithToken()
.then(applicationJsonHeaders => {
const requestOptions = {
method: 'GET',
headers: applicationJsonHeaders,
};
return fetch(process.env.REACT_APP_PROJECTS_API_URL + "/projects", requestOptions)
.then(parseResponseAndHandleErrors)
.then(json => {
dispatch(setAllProjects(json))})
.catch(error => {
console.error(error)
dispatch(failedToLoadProjects(error))
});
})
}}
另外,如前所述,如果您正在测试异步内容,那么必须在测试完成时告诉jest。为此,让您的it调用将done
作为参数,并在验证结果i之后将其作为函数调用。然后()
这只是我这边的一个快速修复。上面的代码中可能仍然有我遗漏的东西或一些bug,但是你明白了
如果您有任何后续问题,请告诉我?如果这对任何人都有用,并且为了感谢Septstium的回答,我最终将代码更改为:
async getHeadersWithToken(requestType) {
if (process.env.REACT_APP_RUNNING_LOCALLY==="true") {
return {
'Accept': 'application/json, text/plain, */*',
'Content-Type': 'application/json'
};
}
let result = await fetch("/.auth/me", this.requestOptions)
let headers = result.json()
.then( json => {
const header = 'Bearer ' + json[0].access_token
const applicationJsonHeaders = this.getJsonHeaders(header, requestType)
return applicationJsonHeaders
})
.catch(error => {
console.error(error)
})
return headers
}
测试的目的是:
const checkActionsWereDispatched = async (expectedActions, actionCreator) => {
const store = mockStore(Map(
{
}),
);
store.dispatch(await actionCreator.apply()).then(() => {
expect(store.getActions()).toEqual(expectedActions)
})
}
it('should create SET_ALL_PROJECTS action when fetching projects', async () => {
fetch
.once(JSON.stringify([{ access_token: "12345" }]))
.once(JSON.stringify({ name: "x" }))
const expectedActions = [
{ type: "SET_ALL_PROJECTS", json: { name: "x" } },
]
checkActionsWereDispatched(expectedActions, actions.loadAllProjects)
});
如上所述,我认为Spetastium的测试版本比我的更容易阅读,他的文章非常有用。哪个
then()
?store.dispatch(actions.loadAllProjects.apply())。那么store
是从哪里导入的呢?我将该存储添加到了问题中。虽然如此,我还是有点惊讶于它能起作用,您不需要向it
提供done
回调,以便它知道测试已完成吗?请参阅。感谢您抽出时间回复。最后,我更改了代码本身(见下一篇文章)。我更喜欢你的测试版本,因为它更可读。没问题。希望它对您有效,并且您对代码D感到满意
async getHeadersWithToken(requestType) {
if (process.env.REACT_APP_RUNNING_LOCALLY==="true") {
return {
'Accept': 'application/json, text/plain, */*',
'Content-Type': 'application/json'
};
}
let result = await fetch("/.auth/me", this.requestOptions)
let headers = result.json()
.then( json => {
const header = 'Bearer ' + json[0].access_token
const applicationJsonHeaders = this.getJsonHeaders(header, requestType)
return applicationJsonHeaders
})
.catch(error => {
console.error(error)
})
return headers
}
export const loadAllProjects = () => {
return async dispatch => {
const authenticator = new Authenticator()
let applicationJsonHeaders = await authenticator.getHeadersWithToken(constants.GET)
let loggedInUser = await authenticator.getLoggedInUser()
const requestOptions = {
method: 'GET',
headers: applicationJsonHeaders,
};
return await fetch(process.env.REACT_APP_PROJECTS_API_URL + "/projects", requestOptions)
.then(response => {
return parseResponseAndHandleErrors(response)
})
.then(json => dispatch(setAllProjects(json)))
.then(()=> dispatch(setAuthenticationData(loggedInUser)))
.catch(error => {
console.error(error)
return dispatch(failedToLoadProjects(error))
});
}
}
const checkActionsWereDispatched = async (expectedActions, actionCreator) => {
const store = mockStore(Map(
{
}),
);
store.dispatch(await actionCreator.apply()).then(() => {
expect(store.getActions()).toEqual(expectedActions)
})
}
it('should create SET_ALL_PROJECTS action when fetching projects', async () => {
fetch
.once(JSON.stringify([{ access_token: "12345" }]))
.once(JSON.stringify({ name: "x" }))
const expectedActions = [
{ type: "SET_ALL_PROJECTS", json: { name: "x" } },
]
checkActionsWereDispatched(expectedActions, actions.loadAllProjects)
});