如何使用 jest 和 react-testing-library 测试上下文提供的函数?

Den*_*nez 6 reactjs jestjs react-testing-library

我有一个<UserProvider />提供上下文的组件,login它的值中有一个方法。在我的测试中,我想检查该方法是否已被调用。如果来自上下文,我如何检查以确保在我的测试中调用此方法?我试过使用spyOnmock方法,但我无法让它们工作。

这是我UserProvider提供上下文的组件。

import React, { useState, useContext, createContext } from 'react'

const UserContext = createContext()

function UserProvider({ children }) {
  const [user, setUser] = useState(null)
  const login = user => setUser(user)

  return <UserContext.Provider value={{ user, login }}>{children}</UserContext.Provider>
}

const useUser = () => useContext(UserContext)

export { UserProvider, useUser }
Run Code Online (Sandbox Code Playgroud)

这是我的Login组件,使用来自UserProvider(via useUser)的上下文

import React from 'react'
import { useUser } from './UserProvider'

function Login() {
  const { login } = useUser()

  const handleSubmit = async e => {
    e.preventDefault()

    // I need to make sure this method is being called in my test.
    login({ name: 'John Doe' })
  }

  return (
    <form onSubmit={handleSubmit}>
      <button>Login</button>
    </form>
  )
}

export default Login
Run Code Online (Sandbox Code Playgroud)

这是我的Login测试

import React from 'react'
import { render, fireEvent } from '@testing-library/react'
import Login from './Login'
import { UserProvider, useUser } from './UserProvider'

// Is this correct?
jest.mock('./UserProvider', () => ({
  useUser: jest.fn(() => ({
    login: jest.fn()
  }))
}))

it('should log a user in', () => {
  const { getByText } = render(
    <UserProvider>
      <Login />
    </UserProvider>
  )

  const submitButton = getByText(/login/i)
  fireEvent.click(submitButton)

  // How can I make this work?
  const { login } = useUser()
  expect(login).toHaveBeenCalledTimes(1)
})
Run Code Online (Sandbox Code Playgroud)

我有一个代码和框,但它出错了 jest.mock 不是一个函数,所以我不知道它是否非常有用。

And*_*eng 11

如果不稍微更改源代码,我就无法让它工作。

首先,我必须导出实际上下文

export { UserProvider, useUser, UserContext }
Run Code Online (Sandbox Code Playgroud)

我们可以使用模拟login函数重新创建提供程序,以下测试将为您服务。

import React from 'react'
import { render, fireEvent } from '@testing-library/react'
import Login from './Login'
import { UserProvider, useUser, UserContext } from './UserProvider'

it('should log a user in', () => {
  const login = jest.fn();
  const { getByText } = render(
    <UserContext.Provider value={{ login }}>
      <Login />
    </UserContext.Provider>
  );

  const submitButton = getByText('Login');
  fireEvent.click(submitButton);

  expect(login).toHaveBeenCalledTimes(1)
});

Run Code Online (Sandbox Code Playgroud)

这完全有可能不是最好的方法。我希望它有帮助。