我是刚开始使用Jest和Enzyme。我有一个组件,它设置一些从父组件传递下来的道具。根据所调用的API调用,我想确保相应地设置这些道具。在此代码中,我想测试是否正确调用了setUser
的user
。这是我的代码:
LoginButton.js
import React, { useState } from 'react';
import { useHistory } from 'react-router-dom';
import './LoginButton.css';
const LoginButton = (props) => {
const history = useHistory();
const [user, setUser] = useState({});
const login = async (e) => {
e.preventDefault();
const loginRequest = {
userName: props.username,
password: props.password
};
try {
const loginResponse = await fetch('/login', {
method: 'POST',
body: JSON.stringify(loginRequest),
headers: {
'Content-Type': 'application/json',
}
});
const user = await loginResponse.json();
console.log("User: ", user);
if (user.status && user.message) {
props.setSubmitError(user.message);
} else if (user.userStatus && user.userStatus === "Locked" || user.userStatus === "Deactivated") {
props.setSubmitError(user.message);
} else {
setUser(user);
// TODO: do something with user, pass it to dashboard component
history.push('/dashboard');
}
} catch (err) {
props.setSubmitError(user.message);
}
}
return (
<button styleName="sign-in-btn" onClick={login}>
Sign me in!
</button>
)
}
export default LoginButton;
这是我在LoginButton.test.js中这样做的尝试:
// mock useHistory or else it will fail in every test
jest.mock('react-router-dom', () => ({
useHistory: () => ({
push: jest.fn()
})
}));
describe('LoginButton', () => {
const setUser = jest.fn();
const useStateSpy = jest.spyOn(React, 'useState');
useStateSpy.mockImplementation((init) => [init, setUser]);
it('sets user state properly', () => {
let props = {
setSubmitError: jest.fn()
}
const fakeResponse = {userName: "user123", success: true};
const mockJsonPromise = Promise.resolve(fakeResponse);
const mockFetchPromise = Promise.resolve({
json: () => {
mockJsonPromise
}
});
global.fetch = jest.fn().mockImplementation(mockFetchPromise);
const wrapper = shallow(<LoginButton
{...props}
/>);
const signInButton = wrapper.find('button')
signInButton.simulate('click', {
preventDefault: () => {},
});
expect(global.fetch).toHaveBeenCalledTimes(1);
// here i expect setUser to have been called already.. but I get an error saying number of calls: 0
expect(setUser).toHaveBeenCalledWith(fakeResponse);
global.fetch.mockClear();
delete global.fetch;
});
})
不幸的是,我收到一条错误消息,说从未调用过setUser,我不确定为什么。我觉得我已经正确设置了测试,并且根据传入的fakeResponse
,我相信它应该进入m else
语句并正确设置用户。任何帮助,将不胜感激。谢谢
简短的答案是:不要。
您不需要测试setUser
。这是实现细节,并且在组件内部。如果看起来有用,您可以测试setSubmitError
回调或history.push
被调用(您可能还需要onSuccess
处理函数来传递返回的用户,因此您也可以对其进行测试)。但是测试像状态设置程序这样的纯内部实现违反了black box testing的原理。
如果您真的想在测试login
函数时获得特定说明,请考虑将其提取为辅助函数,可以在组件上下文之外进行测试。这样就更清楚了给定输入的预期输出是什么。