用 jest 和酵素测试 React 组件
Posted
技术标签:
【中文标题】用 jest 和酵素测试 React 组件【英文标题】:Tests React component with jest and enzyme 【发布时间】:2020-08-12 17:18:59 【问题描述】:我有下面介绍的组件。我是单元测试的新手。任何人都可以给任何人建议我应该如何以及在这个组件中测试什么?我试图浅渲染它,检查 h2 中的文本是否存在,但我仍然收到错误。
import React, useEffect from 'react';
import Form, Field from 'react-final-form';
import useHistory, Link from 'react-router-dom';
import useDispatch, useSelector from 'react-redux';
import loginUser, clearErrorMessage from '../../redux/auth/authActions';
import Input from '../Input/Input';
import ROUTES from '../../routes/routes';
import './LoginForm.scss';
const LoginForm = () =>
const dispatch = useDispatch();
const history = useHistory();
const loading, isLogged, errorMessage = useSelector(state => state.auth);
useEffect(() =>
if (isLogged)
history.push('/');
return () =>
dispatch(clearErrorMessage());
;
, [dispatch, history, isLogged]);
const handleSubmitLoginForm = values =>
if (!loading)
dispatch(loginUser(values));
;
const validate = ( password ) =>
const errors = ;
if (!password)
errors.password = 'Enter password!';
return errors;
;
return (
<article className="login-form-wrapper">
<h2>SIGN IN</h2>
<Form onSubmit=handleSubmitLoginForm validate=validate>
( handleSubmit ) => (
<form onSubmit=handleSubmit autoComplete="off" className="login-form">
<div className="login-form__field">
<Field name="email" component=Input type="email" label="E-mail" />
</div>
<div className="login-form__buttons">
<button type="submit" className=loading ? 'button-disabled' : ''>
Sign in
</button>
</div>
</form>
)
</Form>
</article>
);
;
export default LoginForm;
我愿意接受任何建议:)
【问题讨论】:
【参考方案1】:首先,我不建议在您的测试中使用shallow
,而here 是一篇很棒的文章。
我还建议使用 react-testing-library 而不是 Enzyme,因为它更好用。
现在,回答您的问题。您在这里使用了redux
和react-router
的钩子,因此您需要为测试中的组件提供必要的数据,以便它可以使用这些钩子。让我向您展示一个示例测试(检查h2
元素中的文本):
import React from 'react';
import mount from 'enzyme';
import Provider from 'react-redux';
import MemoryRouter, Route from 'react-router';
import LoginForm from './LoginForm';
describe('Login Form', () =>
it('should have SIGN IN header', () =>
const store = createStore();
const component = mount(
<Provider store=store>
<MemoryRouter initialEntries=['/login']>
<Route path="/:botId" component=LoginForm />
</MemoryRouter>
</Provider>
)
expect(component.find('h2').text()).toEqual('SIGN IN');
);
);
对这个例子的一些解释。
我使用mount
而不是shallow
,因为我更喜欢在测试中尽可能多地进行渲染,这样我就可以检查一切是否正常工作。
您可以看到我并没有直接渲染我的组件,而是将它与其他组件包装在一起(Provider
来自react-redux
和MemoryRouter
来自react-router
)。为什么?因为我需要为我的组件提供 context。在这种情况下,它是 redux
和 router
上下文,因此内部使用的数据存在并且可以找到(例如,useSelector(state => state.auth)
必须提供一些状态,以便它可以访问 auth
属性)。如果您删除其中任何一个,您会收到一些错误消息,提示此上下文丢失 - 请自行检查:)。
有关使用 router
上下文进行测试的一些详细信息,请参阅 here
至于在我的示例中使用redux
进行测试,我没有定义一个createStore
函数,因为有几种方法可以解决这个问题。其中之一涉及创建一个您在生产应用程序中使用的真实商店。这是我更喜欢的一个,我的同事围绕这个主题写了一篇很棒的文章here。其他是创建某种模拟商店,例如this article。同样,我更喜欢第一种方法,但无论哪种方式更适合您。
回答您在此示例中应该测试什么的其他问题。有多种可能性。这主要取决于您的业务案例,但我将在此处测试的示例包括:
在输入中输入内容,单击按钮并观察登录是否成功(通过重定向到新路径 - 在本例中为/
)
未输入密码并单击按钮 - 应显示错误
检查按钮类在加载时是否发生变化
不要在已经加载时分派登录操作两次
等等……
这实际上只是围绕测试编写的内容的冰山一角,但我希望它对您有所帮助,并为您深入研究该主题提供了一个良好的开端。
【讨论】:
你应该小心阅读一篇文章并相信它。我不同意那篇文章。 你指的是哪篇文章?关于浅渲染?如果是这样,这不仅仅是一篇文章——我已经用了很长时间了,但它带来的问题非常多(尤其是在重构的情况下,一段时间后就变得不可能了)所以我就停止使用它了一切都变得简单多了。我同意可能有不同的测试方法,但这对我有用,shallow
阻止了我免费重构的可能性,而无需担心破坏测试。以上是关于用 jest 和酵素测试 React 组件的主要内容,如果未能解决你的问题,请参考以下文章
如何使用react-test-renderer和jest测试包含嵌套组件的反应组件?