用 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,因为它更好用。

现在,回答您的问题。您在这里使用了reduxreact-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-reduxMemoryRouter 来自react-router)。为什么?因为我需要为我的组件提供 context。在这种情况下,它是 reduxrouter 上下文,因此内部使用的数据存在并且可以找到(例如,useSelector(state =&gt; state.auth) 必须提供一些状态,以便它可以访问 auth 属性)。如果您删除其中任何一个,您会收到一些错误消息,提示此上下文丢失 - 请自行检查:)。 有关使用 router 上下文进行测试的一些详细信息,请参阅 here 至于在我的示例中使用redux 进行测试,我没有定义一个createStore 函数,因为有几种方法可以解决这个问题。其中之一涉及创建一个您在生产应用程序中使用的真实商店。这是我更喜欢的一个,我的同事围绕这个主题写了一篇很棒的文章here。其他是创建某种模拟商店,例如this article。同样,我更喜欢第一种方法,但无论哪种方式更适合您。

回答您在此示例中应该测试什么的其他问题。有多种可能性。这主要取决于您的业务案例,但我将在此处测试的示例包括:

在输入中输入内容,单击按钮并观察登录是否成功(通过重定向到新路径 - 在本例中为 /) 未输入密码并单击按钮 - 应显示错误 检查按钮类在加载时是否发生变化 不要在已经加载时分派登录操作两次

等等……

这实际上只是围绕测试编写的内容的冰山一角,但我希望它对您有所帮助,并为您深入研究该主题提供了一个良好的开端。

【讨论】:

你应该小心阅读一篇文章并相信它。我不同意那篇文章。 你指的是哪篇文章?关于浅渲染?如果是这样,这不仅仅是一篇文章——我已经用了很长时间了,但它带来的问题非常多(尤其是在重构的情况下,一段时间后就变得不可能了)所以我就停止使用它了一切都变得简单多了。我同意可能有不同的测试方法,但这对我有用,shallow 阻止了我免费重构的可能性,而无需担心破坏测试。

以上是关于用 jest 和酵素测试 React 组件的主要内容,如果未能解决你的问题,请参考以下文章

如何使用react-test-renderer和jest测试包含嵌套组件的反应组件?

Jest+Enzyme测试React组件(上)

使用 React Suspense 和 React.lazy 子组件进行 Jest/Enzyme 类组件测试

React 和 Jest,如何测试更改状态并检查另一个组件

用 Jest 测试 React 应用程序:意外的令牌

使用 Jest 和 Enzyme 测试使用 Redux 的功能性 React 组件