[React Testing] Mock HTTP Requests with jest.mock in React Component Tests

If you have a component that makes HTTP requests, you’ll probably want to mock those out for UI unit and integration tests. Let’s see how to use jest’s built-in mocking capabilities to do that.

Component:

import React from 'react'
import { loadGreeting } from './api'

function GreetingLoader() {
  const [greeting, setGreeting] = React.useState('')
  async function loadGreetingForInput(e) {
    e.preventDefault()
    const { data } = await loadGreeting(e.target.elements.name.value)
    setGreeting(data.greeting)
  }
  return (
    <form onSubmit={loadGreetingForInput}>
      <label htmlFor="name">Name</label>
      <input id="name" />
      <button type="submit">Load Greeting</button>
      <div aria-label="greeting">{greeting}</div>
    </form>
  )
}

export { GreetingLoader }

API:

const sleep = (time) =>
  new Promise((resolve) => {
    setTimeout(resolve, time)
  })

const greetings = ['Hello', 'Hi', 'Hey there', `What's up`, 'Howdy', `G'day`]

async function loadGreeting(subject) {
  return { data: { greeting: `${await fetchRandomGreeting()} ${subject}` } }
}

async function fetchRandomGreeting() {
  await sleep(1000)
  return greetings[Math.floor(Math.random() * greetings.length)]
}

Testing:

import React from 'react'
import { render, fireEvent, wait } from '@testing-library/react'
import { loadGreeting as mockLoadGreeting } from './api'
import { GreetingLoader } from './greeting-loader-01-mocking'

// mock all the export from api module
jest.mock('../api')

test('loads greeting on click', async () => {
  const testGreeting = 'TEST_GREETING'
  // Mock the data return
  mockLoadGreeting.mockResolvedValueOnce({ data: { greeting: testGreeting } })
  const { getByLabelText, getByText } = render(<GreetingLoader />)
  const nameInput = getByLabelText(/name/i)
  const loadButton = getByText(/load/i)
  nameInput.value = 'Mary'
  fireEvent.click(loadButton)
  expect(mockLoadGreeting).toHaveBeenCalledWith('Mary')
  expect(mockLoadGreeting).toHaveBeenCalledTimes(1)
  // using wait until to avoid warning from React
  await wait(() =>
    expect(getByLabelText(/greeting/i)).toHaveTextContent(testGreeting),
  )
})

猜你喜欢

转载自www.cnblogs.com/Answer1215/p/12810822.html
今日推荐