使用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通过导出来编写测试。但是如何测试validateFormhandleSubmit方法呢?如果它是基于类的组件,那么我可以将组件变浅,并从实例中将其用作

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));

};

....

这样,您就可以单独测试isPasswordValidisEmailValid,然后测试时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

回到顶部