Exemplo
Esta página foi traduzida por PageTurner AI (beta). Não é oficialmente endossada pelo projeto. Encontrou um erro? Reportar problema →
Início Rápido
Esta é uma configuração mínima para você começar. Se quiser ver uma descrição do que cada linha faz, role até a versão comentada. Role até Exemplo Completo para ver uma configuração de teste mais avançada.
import {render, screen} from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import '@testing-library/jest-dom'
import Fetch from './fetch'
test('loads and displays greeting', async () => {
// ARRANGE
render(<Fetch url="/greeting" />)
// ACT
await userEvent.click(screen.getByText('Load Greeting'))
await screen.findByRole('heading')
// ASSERT
expect(screen.getByRole('heading')).toHaveTextContent('hello there')
expect(screen.getByRole('button')).toBeDisabled()
})
Quickstart (Annotated Example)
// import react-testing methods
import {render, screen} from '@testing-library/react'
// userEvent library simulates user interactions by dispatching the events that would happen if the interaction took place in a browser.
import userEvent from '@testing-library/user-event'
// add custom jest matchers from jest-dom
import '@testing-library/jest-dom'
// the component to test
import Fetch from './fetch'
test('loads and displays greeting', async () => {
// Render a React element into the DOM
render(<Fetch url="/greeting" />)
await userEvent.click(screen.getByText('Load Greeting'))
// wait before throwing an error if it cannot find an element
await screen.findByRole('heading')
// assert that the alert message is correct using
// toHaveTextContent, a custom matcher from jest-dom.
expect(screen.getByRole('heading')).toHaveTextContent('hello there')
expect(screen.getByRole('button')).toBeDisabled()
})
Exemplo Completo
Veja as seções a seguir para uma análise detalhada do teste
Recomendamos usar a biblioteca Mock Service Worker (MSW) para simular declarativamente a comunicação de API em seus testes, em vez de fazer stubbing do window.fetch ou depender de adaptadores de terceiros.
Nosso exemplo aqui usa axios para fazer chamadas de API. Se sua aplicação usa fetch() para chamadas de API, saiba que por padrão o JSDOM não inclui fetch. Se você usa vitest como test runner, ele será incluído automaticamente. Para jest, você pode adicionar manualmente um polyfill para fetch() ou usar o ambiente jest-fixed-jsdom que inclui fetch.
import React from 'react'
import {http, HttpResponse} from 'msw'
import {setupServer} from 'msw/node'
import {render, fireEvent, screen} from '@testing-library/react'
import '@testing-library/jest-dom'
import Fetch from '../fetch'
const server = setupServer(
http.get('/greeting', () => {
return HttpResponse.json({greeting: 'hello there'})
}),
)
beforeAll(() => server.listen())
afterEach(() => server.resetHandlers())
afterAll(() => server.close())
test('loads and displays greeting', async () => {
render(<Fetch url="/greeting" />)
fireEvent.click(screen.getByText('Load Greeting'))
await screen.findByRole('heading')
expect(screen.getByRole('heading')).toHaveTextContent('hello there')
expect(screen.getByRole('button')).toBeDisabled()
})
test('handles server error', async () => {
server.use(
http.get('/greeting', () => {
return new HttpResponse(null, {status: 500})
}),
)
render(<Fetch url="/greeting" />)
fireEvent.click(screen.getByText('Load Greeting'))
await screen.findByRole('alert')
expect(screen.getByRole('alert')).toHaveTextContent('Oops, failed to fetch!')
expect(screen.getByRole('button')).not.toBeDisabled()
})
Passo a Passo
Imports
// import dependencies
import React from 'react'
// import API mocking utilities from Mock Service Worker
import {http, HttpResponse} from 'msw'
import {setupServer} from 'msw/node'
// import react-testing methods
import {render, fireEvent, screen} from '@testing-library/react'
// add custom jest matchers from jest-dom
import '@testing-library/jest-dom'
// the component to test
import Fetch from '../fetch'
test('loads and displays greeting', async () => {
// Arrange
// Act
// Assert
})
Mock
Use a função setupServer do msw para simular uma requisição de API feita pelo nosso componente testado.
// declare which API requests to mock
const server = setupServer(
// capture "GET /greeting" requests
http.get('/greeting', (req, res, ctx) => {
// respond using a mocked JSON body
return HttpResponse.json({greeting: 'hello there'})
}),
)
// establish API mocking before all tests
beforeAll(() => server.listen())
// reset any request handlers that are declared as a part of our tests
// (i.e. for testing one-time error scenarios)
afterEach(() => server.resetHandlers())
// clean up once the tests are done
afterAll(() => server.close())
// ...
test('handles server error', async () => {
server.use(
// override the initial "GET /greeting" request handler
// to return a 500 Server Error
http.get('/greeting', (req, res, ctx) => {
return new HttpResponse(null, {status: 500})
}),
)
// ...
})
Arrange (Preparação)
O método render renderiza um elemento React no DOM.
render(<Fetch url="/greeting" />)
Act (Ação)
O método fireEvent permite disparar eventos para simular ações do usuário.
fireEvent.click(screen.getByText('Load Greeting'))
// wait until the `get` request promise resolves and
// the component calls setState and re-renders,
// throwing an error if it cannot find an element
await screen.findByRole('heading')
Assert (Verificação)
// assert that the alert message is correct using
// toHaveTextContent, a custom matcher from jest-dom.
expect(screen.getByRole('alert')).toHaveTextContent('Oops, failed to fetch!')
// assert that the button is not disabled using
// toBeDisabled, a custom matcher from jest-dom.
expect(screen.getByRole('button')).not.toBeDisabled()
Sistema Sob Teste (SUT)
import React, {useState, useReducer} from 'react'
import axios from 'axios'
const initialState = {
error: null,
greeting: null,
}
function greetingReducer(state, action) {
switch (action.type) {
case 'SUCCESS': {
return {
error: null,
greeting: action.greeting,
}
}
case 'ERROR': {
return {
error: action.error,
greeting: null,
}
}
default: {
return state
}
}
}
export default function Fetch({url}) {
const [{error, greeting}, dispatch] = useReducer(
greetingReducer,
initialState,
)
const [buttonClicked, setButtonClicked] = useState(false)
const fetchGreeting = async url =>
axios
.get(url)
.then(response => {
const {data} = response
const {greeting} = data
dispatch({type: 'SUCCESS', greeting})
setButtonClicked(true)
})
.catch(error => {
dispatch({type: 'ERROR', error})
})
const buttonText = buttonClicked ? 'Ok' : 'Load Greeting'
return (
<div>
<button onClick={() => fetchGreeting(url)} disabled={buttonClicked}>
{buttonText}
</button>
{greeting && <h1>{greeting}</h1>}
{error && <p role="alert">Oops, failed to fetch!</p>}
</div>
)
}