我正在尝试测试loadAllProjects函数。
测试在.then()失败并出现错误:TypeError:无法读取属性'然后'未定义的
我也尝试过模拟getHeadersWithToken()的响应但是无法让它工作。
对此问题嗤之以鼻,并感谢任何帮助。
试验:
it('should create SET_ALL_PROJECTS action when fetching projects', () => {
fetch
.once(JSON.stringify([{ access_token: "12345" }]))
.once(JSON.stringify({ name: "x" }))
const expectedActions = [
{ type: "SET_ALL_PROJECTS", json: { name: "x" } },
]
store.dispatch(actions.loadAllProjects.apply())
.then(() => { // FAILS HERE
expect(store.getActions()).toEqual(expectedActions)
})
});
代码:
export const getHeadersWithToken = () => {
return fetch("/.auth/me", requestOptions)
.then(parseResponseAndHandleErrors)
.then(json => {
const header = 'Bearer ' + json[0].access_token
const applicationJsonHeaders = getJsonHeaders(header)
return applicationJsonHeaders
})
.catch( error=> {
console.error(error)
})
}
export const loadAllProjects = () => {
return (dispatch) => {
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))
});
})
}
}
测试中使用的商店:
const store = mockStore(Map(
{
allProjects: Map({
}),
currentProject: Map({
authenticationData: Map({
})
})
})
);
答案 0 :(得分:0)
您正在使用哪种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();
})
});
您还需要修改loadAllProjects的代码,以便内部函数返回promise:
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))
});
})
}}
此外,如前所述,如果您正在测试异步内容,则必须告诉玩笑何时完成测试。通过让您的it调用将done
作为参数,并在.then()
这只是我的快速解决方案。上面的代码中可能仍然缺少某些东西或一些错误,但是您明白了。
让我知道您是否有任何后续问题?
答案 1 :(得分:0)
万一这对任何人都有用,并且为了确认Septastium的回答,我最终将代码更改为:
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)
});
如上所述,我认为Spetastium的测试版本比我的更容易阅读,他的文章here很有帮助。