Testing Library是一个使用非常方便的测试辅助工具
安装
在脚手架创建的react项目中开箱即用
npm install --save-dev @testing-library/react
组件
一个类似官网的示例
import React, { useState, useReducer } from 'react'
import axios from "axios"
const initState = {
error: null,
greet: null
}
function greetReducer(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}) {
//一个react的useReducer hooks
const [{error,greeting}, dispatch] = React.useReducer(greetReducer, initState);
//state hook
const [buttonClick,setButtonClick] = React.useState(false);
const [urlState,setUrlState] = React.useState(url);
//请求数据,在这里我们使用msw模拟,但在这里我们不重点介绍
let fetchGreeting = async ()=>{
//使用axios获取数据,更新greeting和按钮的状态
axios.get(urlState).then(response=>{
const { data } = response;
const {greeting} = data;
dispatch({type:"SUCCESS", greeting})
setButtonClick("/hello" !== urlState)
}).catch(error=>{
dispatch({ type: 'ERROR', error })
})
};
//改变请求的url,实际使用中不会有这样的操作
function change(){
setUrlState("/hello")
}
//渲染后立刻获取数据
React.useEffect(()=>{
fetchGreeting()
},[urlState])
//按钮的文本状态
const buttonText = buttonClick ? "OK" : "Loading";
return <div>
<button onClick={fetchGreeting} disabled={buttonClick}>
{buttonText}
</button>
<button onClick={change} >
changeUrl
</button>
{greeting && <h1 role="heading">{greeting}</h1>}
{error && <p role="alert">Oops, failed to fetch!</p>}
</div>
}
测试
import React from "react"
import { render, fireEvent, waitForElement, screen } from '@testing-library/react'
import '@testing-library/jest-dom/extend-expect'
import Fetch from "./Fetch"
import {act} from "react-dom/test-utils";
describe("greeting",()=>{
test('loads and displays greeting', async () => {
//准备组件的渲染
act(()=>{
render(<Fetch url="/greeting" />)
//触发按钮事件,实际上不需要,因为我们在useEffect中依旧加载了,但为了测试,这里依然进行触发
fireEvent.click(screen.getByText('Loading'))
})
//等到role为heading元素显示出来时,即当请求成功返回后
await waitForElement(() => screen.getByRole('heading'))
//期望role为heading元素的内容为hello there
expect(screen.getByRole('heading')).toHaveTextContent('hello there')
//期望第一个按钮的状态为不可用的
expect(screen.getAllByRole('button')[0]).toBeDisabled()
})
test("changeUrl", async()=>{
act(()=>{
render(<Fetch url="/greeting" />)
//组件加载后触发文本为changeUrl的按钮,即改变请求的url
fireEvent.click(screen.getByText('changeUrl'))
})
//等到role为heading元素显示出来时
await waitForElement(() => screen.getByRole('heading'))
//期望role为heading元素的内容为hello world
expect(screen.getByRole('heading')).toHaveTextContent('hello world')
//期望第一个按钮的状态为可用的
expect(screen.getAllByRole('button')[0]).not.toBeDisabled()
})
})
除开之前介绍的act外,在这个测试用例中我们还用到了React 测试库的render, fireEvent, waitForElement, screen;
render:渲染测试的组件,即可以看做将组件渲染到屏幕上(虚拟的)
screen: 用于获取我们需要的节点,结合render可以很形象的看成从屏幕上获取我们要的东西
fireEvent: 触发事件,相比Test Utilities的buttons[0].dispatchEvent(new MouseEvent(‘click’, {bubbles: true})),这个好用多了
waitForElement:等待某个元素出现后,相似的还有waitForElementToBeRemoved,waitFor等
除开上面介绍的,Testing Library还有很多的很实用的方法,除开用来测试react外,还可以测试原生js写的DOM节点,vue等,如果有需要的话可以到官网查看