使用Jest使用Hooks测试React功能组件
因此,我正在从基于类的组件转移到功能组件,但在使用jest / zyme编写功能组件内部的方法(显式使用钩子)编写测试时陷入困境。这是我的代码的精简版。
function validateEmail(email: string): boolean { return email.includes('@');
}
const Login: React.FC<IProps> = (props) => {
const [isLoginDisabled, setIsLoginDisabled] = React.useState<boolean>(true);
const [email, setEmail] = React.useState<string>('');
const [password, setPassword] = React.useState<string>('');
React.useLayoutEffect(() => {
validateForm();
}, [email, password]);
const validateForm = () => {
setIsLoginDisabled(password.length < 8 || !validateEmail(email));
};
const handleEmailChange = (evt: React.FormEvent<HTMLFormElement>) => {
const emailValue = (evt.target as HTMLInputElement).value.trim();
setEmail(emailValue);
};
const handlePasswordChange = (evt: React.FormEvent<HTMLFormElement>) => {
const passwordValue = (evt.target as HTMLInputElement).value.trim();
setPassword(passwordValue);
};
const handleSubmit = () => {
setIsLoginDisabled(true);
// ajax().then(() => { setIsLoginDisabled(false); });
};
const renderSigninForm = () => (
<>
<form>
<Email
isValid={validateEmail(email)}
onBlur={handleEmailChange}
/>
<Password
onChange={handlePasswordChange}
/>
<Button onClick={handleSubmit} disabled={isLoginDisabled}>Login</Button>
</form>
</>
);
return (
<>
{renderSigninForm()}
</>);
};
export default Login;
我知道我可以validateEmail
通过导出来编写测试。但是如何测试validateForm
或handleSubmit
方法呢?如果它是基于类的组件,那么我可以将组件变浅,并从实例中将其用作
const wrapper = shallow(<Login />);wrapper.instance().validateForm()
但这不适用于功能组件,因为无法以这种方式访问内部方法。有什么方法可以访问这些方法,还是应该在测试时将功能组件视为黑盒?
回答:
我认为,您不必担心单独测试FC内部的方法,而不必担心其副作用。例如:
it('should disable submit button on submit click', () => { const wrapper = mount(<Login />);
const submitButton = wrapper.find(Button);
submitButton.simulate('click');
expect(submitButton.prop('disabled')).toBeTruthy();
});
由于您可能正在使用异步的useEffect,因此您可能希望将期望包装在 :
setTimeout(() => { expect(submitButton.prop('disabled')).toBeTruthy();
});
您可能想做的另一件事是,提取与与表单介绍纯函数进行交互无关的任何逻辑。例如:代替:
setIsLoginDisabled(password.length < 8 || !validateEmail(email));
您可以重构:
Helpers.js
export const isPasswordValid = (password) => password.length > 8;export const isEmailValid = (email) => {
const regEx = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return regEx.test(email.trim().toLowerCase())
}
LoginComponent.jsx
import { isPasswordValid, isEmailValid } from './Helpers';....
const validateForm = () => {
setIsLoginDisabled(!isPasswordValid(password) || !isEmailValid(email));
};
....
这样,您就可以单独测试isPasswordValid
和isEmailValid
,然后测试时Login
组件,你可以嘲笑你的进口。然后剩下的唯一要测试的Login
组件就是单击,调用导入的方法,然后基于这些响应的行为,例如:
- it('should invoke isPasswordValid on submit')- it('should invoke isEmailValid on submit')
- it('should disable submit button if email is invalid') (isEmailValid mocked to false)
- it('should disable submit button if password is invalid') (isPasswordValid mocked to false)
- it('should enable submit button if email is invalid') (isEmailValid and isPasswordValid mocked to true)
这种方法的主要优点在于,Login
组件应该只处理 而无需执行其他任何操作。可以直接测试。任何其他逻辑
(关注点分离)。
以上是 使用Jest使用Hooks测试React功能组件 的全部内容, 来源链接: utcz.com/qa/404105.html