使用 Jest 和 React 测试库测试 Apollo React Hooks

Posted

技术标签:

【中文标题】使用 Jest 和 React 测试库测试 Apollo React Hooks【英文标题】:Testing Apollo React Hooks with Jest & React Testing Library 【发布时间】:2020-03-24 16:29:30 【问题描述】:

我有一个使用 Apollo 突变钩子的表单:

import React from 'react'
import  useFormik  from 'formik'
import  useLoginMutation  from '../generated'

const LoginContainer = () => 
  const [loginMutation,  data, loading, error ] = useLoginMutation()

  const formik = useFormik(
    initialValues: 
      email: '',
      password: '',
    ,
    onSubmit: values => 
      loginMutation(
        variables: 
          input: 
            email: String(values.email).trim(),
            password: values.password,
          ,
        ,
      )
    ,
  )

  return (
    <form
      onSubmit=event => 
        event.preventDefault()
        formik.handleSubmit(event)
      
    >
      <input
        data-testid="login-email-input"
        name="email"
        placeholder="Email address"
        //  label="Email"
        required
        type="email"
        value=formik.values.email
        onChange=formik.handleChange
      />
      <input
        data-testid="login-password-input"
        name="password"
        placeholder="password"
        //  label="Password"
        required
        type="password"
        value=formik.values.password
        onChange=formik.handleChange
      />
      <button data-testid="login-submit-input" type="submit">
        LOGIN
      </button>
    </form>
  )


export default LoginContainer

我试图确保在用户填写表单并单击提交按钮时调用登录突变。

测试有时会成功运行,有时会失败。我怀疑 loginMutation 承诺在运行期望块之前没有得到解决。

控制台也有以下警告:

  Warning: An update to LoginContainer inside a test was not wrapped in act(...).

    When testing, code that causes React state updates should be wrapped into act(...):

    act(() => 
      /* fire events that update state */
    );
    /* assert on the output */

这是测试:

describe('login container', () => 
  let loginMutationCalled = false

  const variables = 
    input: 
      email: 'test@example.com',
      password: '123',
    ,
  

  const result = () => 
    loginMutationCalled = true
    return 
      data: 
        Login: 
          accountId: '123',
        ,
      ,
    
  

  const mocks = [
    
      request: 
        query: LOGIN_MUTATION,
        variables,
      ,
      result,
    ,
  ]

  it('should call the login mutation', async () => 
    await act(async () => 
      const  findByTestId  = render(
        <MockedProvider mocks=mocks addTypename=false>
          <LoginContainer />
        </MockedProvider>,
      )

      fireEvent.change(await findByTestId('login-email-input'), 
        target: 
          value: 'test@example.com',
        ,
      )

      fireEvent.change(await findByTestId('login-password-input'), 
        target: 
          value: '123',
        ,
      )

      await wait(async () =>
        fireEvent.click(await findByTestId('login-submit-input')),
      )
    )

    expect(loginMutationCalled).toBe(true)
  )
)

如何确保在运行断言之前已解决 loginMutation 承诺?

【问题讨论】:

【参考方案1】:

请查看我的 GitHub https://github.com/Arit143/mytube-ui/blob/master/src/pages/List.spec.tsx 以获取 async act wait。通常,我将行为包装起来并在一个函数中等待,然后等待它完成。如果您觉得登录解析花费了很多时间,您可以增加wait 的数量。以 GitHub URL 为例,如果您仍然遇到问题,请告诉我。

【讨论】:

以上是关于使用 Jest 和 React 测试库测试 Apollo React Hooks的主要内容,如果未能解决你的问题,请参考以下文章

测试库 React 与 Jest

在 TypeScript 中使用 NextJS 设置 Jest + React 测试库 -- 设置 upp jest.config.js 时出错

如何使用 Jest 和 react-testing-library 测试 react-dropzone?

fireEvent.keyDown 在我的 Jest + React 测试库测试中没有按预期工作

React 测试库 + Jest:如何测试接收数字的组件然后对其进行格式化

使用 react-navigation 中的 useRoute 进行 Jest 单元测试