我在我的一个React组件中有以下异步调用:
onSubmit = (data) => {
this.props.startAddPost(data)
.then(() => {
this.props.history.push('/');
});
};
此处的目标是仅在将帖子保留在Redux中后将用户重定向到索引页面(startAddPost
是异步操作生成器,使用axios将数据发送到外部API并调度另一个操作将在Redux商店中保存新帖子;返回整个内容,以便我可以在组件本身链接then
调用它。它在应用程序中工作得很好,但我在测试时遇到了麻烦。
import React from 'react';
import { shallow } from 'enzyme';
import { AddPost } from '../../components/AddPost';
import posts from '../fixtures/posts';
let startAddPost, history, wrapper;
beforeEach(() => {
startAddPost = jest.fn();
history = { push: jest.fn() };
wrapper = shallow(<AddPost startAddPost={startAddPost} history={history} />);
});
test('handles the onSubmit call correctly', () => {
wrapper.find('PostForm').prop('onSubmit')(posts[0]);
expect(startAddPost).toHaveBeenLastCalledWith(posts[0]);
expect(history.push).toHaveBeenLastCalledWith('/');
});
所以我显然需要通过这个测试,但它失败了,输出如下:
● handles the onSubmit call correctly
TypeError: Cannot read property 'then' of undefined
at AddPost._this.onSubmit (src/components/AddPost.js:9:37)
at Object.<anonymous> (src/tests/components/AddPost.test.js:25:46)
at process._tickCallback (internal/process/next_tick.js:109:7)
那我怎么解决这个问题呢?我怀疑这是测试本身的问题,因为一切都在实际的应用程序中运行良好。谢谢!
答案 0 :(得分:0)
您的代码首先是不可测试的。您将回调传递给操作并在将数据保存到数据库之后执行它,如此,
export function createPost(values, callback) {
const request = axios.post('http://localhost:8080/api/posts', values)
.then(() => callback());
return {
type: CREATE_POST,
payload: request
};
}
在这种情况下,回调应该负责上述重定向。使用该操作的客户端代码应该是这样的。
onSubmit(values) {
this.props.createPost(values, () => {
this.props.history.push('/');
});
}
这使您的行动更灵活,也可以重复使用。
然后,当您测试它时,您可以将存根传递给操作,并验证它是否被调用一次。编写高质量,可测试的代码是一门艺术。
答案 1 :(得分:0)
您的代码存在的问题是startAddPost
函数是一个模拟函数,不返回 Promise ,但您的实际this.props.startAddPost
功能确实返回承诺。
这就是为什么你的代码可以工作但是当你尝试测试它时失败,导致cannot read property....
错误。
要解决此问题,请使您的模拟函数返回Promise
,如此 -
beforeEach(() => {
startAddPost = jest.fn().mockReturnValueOnce(Promise.resolve())
...
});
详细了解mockReturnValueOnce
here。