使用Jest和React测试库的测试案例
作者 Satya Swaroop Mohapatraon July 9, 2021; tagged underreactjs,jest,react-testing-library
当涉及到更好的用户体验,处理bug和修复一个特定的组件或它的一些功能时,Testing ,防止我们的船在生产后😃沉没。
像Jest这样的测试框架,提供了一些功能和方法,通过它们我们可以在项目中进行各种assertions 。
因此,让我们通过使用react创建一个简单的Counter App ,深入了解jest和react-testing-library。
像往常一样,我们将使用cra 模板进行设置
npx create-react-app my-counter
cd my-counter
npm start
让我们创建一个简单的计数器:
import {useState} from "react"
import './App.css';
function App() {
const [count,setCount] = useState(1);
const increment = () => {
setCount(count + 1);
}
const decrement = ()=>{
if(count === 0){
return
}
setCount(count - 1);
}
return (
<div className="App">
<h1>Counter App 😃</h1>
<div className="flex">
<button onClick={increment}>+</button>
<button onClick={decrement}>-</button>
</div>
<div className="App">
<h2 title="Display">{count}</h2>
</div>
</div>
);
}
export default App;
现在我们已经创建了我们的计数器,现在让我们关注一下什么是jest ,react-testing-library ,以及为什么我们要一起使用这些?
Jest
Jest是一个javascript测试框架,它提供了一个混合的断言库,以及一个测试运行器和一个内置的嘲弄库。
React测试库
它是一个测试库,用于渲染反应组件。它直接与DOM节点一起工作,确保我们编写的测试与用户与组件的交互方式非常相似。
为什么我们要一起使用这个?
Jest为我们提供了各种测试块,如it(),test() 和describe() ,用于命名测试和包括各自的代码。它还为我们提供了一个全局断言函数,即expect() ,以进行简单的测试断言。
注意:it() 和test() 是完全相同的,只是在命名上有所不同。
jest-dom 为了使测试案例易于阅读,易于维护,jest ,它提供了一些自定义的匹配器函数,如toBeInTheDocument(),toHaveAttribute() toHaveStyle() 等。与DOM API的交流变得非常容易,就像我们在浏览器中交流一样。
而另一方面,react-testing-libary为我们提供了各种方法,如render() ,以渲染react组件。screen 对象,它有所有的查询,document 对象模型被包裹在<body> 元素中。
由于我们使用的是cra 模板,上述软件包会作为devDependencies自动安装在package.json 文件中。如果我们不使用cra 模板,我们需要手动安装它。
使用npm
npm install --save-dev @testing-library/react @testing-library/jest-dom
或使用yarn
yarn add --dev @testing-library/react @testing-library/jest-dom
现在,让我们看一下setupTest.js 文件,这里我们导入了jest-dom包,这样react就可以在设置测试环境时初始化它。
测试案例
Case-1: Will test if the title "Counter App 😃" is present in the document or not.
Case-2: Will test when the + clicked it should increment the counter by 1.
Case-3: Will test when the - clicked it should decrement the counter by 1.
注意:每当我们写测试用例时,我们的文件命名惯例应该是some-name.test.js 。如果我们的组件目录中有一个some-name.js 文件,我们可以创建一个__test__ 目录,并在其中创建some-name.test.js 文件,这样我们就可以从一个文件级别导入some-name.js 文件。
让我们删除App.test.js 文件中的所有内容并从头开始:
import { render, screen } from '@testing-library/react';
import App from './App';
test('renders Counter App 😃 title', () => {
render(<App />);
const titleElement = screen.getByText(/Counter App 😃/);
expect(titleElement).toBeInTheDocument();
});
这里我们使用render() 方法来渲染整个<App/> 组件,然后我们通过使用getByText() 查询screen 对象来查询标题。然后我们有我们的全局断言函数expect() 和一个匹配器函数toBeInTheDocument() ,它只是测试这个元素是否在DOM中被渲染。
运行该测试:
yarn test
或
npm run test
现在jest 会自动寻找.test.js 文件并执行测试。如果一切正常,测试案例就会通过:

恭喜你 🎉 我们已经写好了第一个测试用例。
让我们通过使用getByRole() 查询来编写其余的测试用例,这里我们也将使用事件处理程序,与我们在浏览器中执行事件的方式相同。我们将使用userEvent来实现。
为了使用这个,我们首先需要手动安装它:
npm install --save-dev @testing-library/user-event @testing-library/dom
或
yarn add --dev @testing-library/user-event @testing-library/dom
import userEvent from "@testing-library/user-event";
test("increment button is clicked and the value increments by 1",()=>{
render(<App/>);
const displayValue = screen.getByTitle("Display");
userEvent.click(screen.getByRole('button',{name: '+'}));
expect(displayValue.textContent).toBe("2");
});
test("decrement button is clicked and the value decrements by 1",()=>{
render(<App/>);
const displayValue = screen.getByTitle("Display");
userEvent.click(screen.getByRole('button',{name: '-'}));
expect(displayValue.textContent).toBe("0");
});
这里我们通过使用getByTitle() 查询,从<App/> 组件中获得<h2> 元素。为了引用确切的元素,我们给它添加了一个title 属性。
之后,我们使用了userEvent ,并给它附加了一个click 事件,然后我们通过使用getByRole 查询从<App/> 获取两个按钮。当我们运行测试时,事件的触发方式与我们在浏览器中执行的click 事件相同。
最后,我们对这两个测试案例进行断言,使其与预期值相符。
你可以在GitHub上查看这些代码。
本博客到此结束。我们将在下一篇博客中重点讨论async 测试。
学习愉快😇!