使用Jest进行react测试
install
npm install --save-dev jest
在package.json文件中添加
{
"scripts": {
"test": "jest"
}
}
之后就可以使用npm run test
跑测试了
如果需要babel的话,还需要安装babel并进行配置
安装babel相关依赖: npm i -D babel-jest @babel-core @babel/preset-env
并创建.babelrc文件,由于需要使用react,所以也添加了react需要的相关配置
{
"presets": [
"@babel/env",
"@babel/react"
],
"plugins": [
"@babel/plugin-proposal-class-properties",
"@babel/plugin-transform-runtime"
]
}
匹配器
跟其他的很多测试框架一样,jest也有很多匹配器供我们去使用,匹配器那么多hhhh。。。看上去就是它本身要表达的意思。
toBe
test exact equality
toEqual
recursively checks every field of an object or array. 递归检查判断
toBeCloseTo
用来比较小数,避免浮点数误差(0.1 + 0.2).toBeCloseTo(0.3)
toBeNull
toBeUndefined
toBeDefined
toBeTruthy
toBeFalsy
(There are only six falsey values in JavaScript: undefined
, null
, NaN
, 0
, ""
, and false
.)
toBeGreaterThan
toBeGreaterThanOrEqual
toBeLessThan
toBeLessThanOrEqual
toMatch
正则匹配。
toContain
判断数组中是否包含指定项。
.toHaveProperty(keyPath, value)
判断对象中是否包含指定属性。
toThrow
判断是否抛出指定的异常。
toBeInstanceOf
判断对象是否是某个类的实例,底层使用 instanceof
。
所有的方法都可以使用.not取反 比如 (0.1 + 0.2).not.toBeCloseTo(0.4)
异步测试
异步测试的方法也很多
关于异步测试,官网说的比较清楚,这里就说一些需要注意的点吧
-
Promse —— resolves && rejects
Jest will wait for that promise to resolve . If the promise is rejected, the test will automatically fail. If you expect a promise to be rejected use the .catch method
在使用resolves或者rejects对Promise进行测试的时候,需要把整个断言作为返回值返回,如果忘了
return
,在fun
函数返回的这个 promise 变为 resolved 状态、也就是then() 执行之前,测试就已经被视为完成了。test('when it resolved', () => { return expect(fun()).resolves.toBe('...'); });
-
done()
如果使用回调函数处理异步,比如fun函数再处理完成时需要调用callback(),如果直接在测试中写如下代码,但是Jest测试在执行结束后才会完成,那么这个测试时时不会工作的。
这个时候使用单个参数调用
done
,而不是将测试放在一个空参数的函数。 Jest会等done
回调函数执行结束后,结束测试。test('...', done => { function callback(data) { expect(data).toBe('...'); done(); } fun(callback); });
-
async && await
可以把resolves/rejects 和 async/await配合使用
test('success', async () => { await expect(fun()).resolves.toBe('...'); }); test('error', async () => { await expect(fun()).rejects.toThrow('error'); });
react component test
需要测试react的时候,需要安装npm i -dev react-test-renderer
去render snapshot
render一个组件之后,生成的snapshot就是对这个组件的节点的渲染结果,在使用npm run test
之后会生成名为__snapshots__
的文件夹,其中的文件格式为component.test.js.snap,snapshot文件也需要提交到代码库中。
在下一次运行测试的时候,新渲染的结果会和之前的snapshot进行比较,如果不同则测试失败,如果变动符合预期,想要更新snapshot,可以通过npm run test:update
来操作。
测试节点
某些情况下,我们需要测试某一个component中的一个节点有没有被渲染或者节点的内容是否符合预期
- 使用testing library
在测试节点的时候,我们可以搭配使用一些testing library,当然使用之前也需要安装——npm i --dev @testing-library/react
-
mock相关依赖和组件
-
mock module
在测试节点之前,如果当前组件中引用了其他的模块,需要先mock组件依赖的模块
jest.mock('../fileName');
-
mock component
如果需要测试的组件中还包括其他组件,为了保证不受其他组件的影响,这个时候我们也需要mock组件引入的其余组件,
比如在Header组件中引用了Context组件,那么就需要mock Context组件,比如Context中为一个div,我们可以直接将Context mock为一个div,其中的内容并不重要
jest.mock('../Context', () => { const MockContext = () => <div>Some Context</div>; return MockContext; });
-
-
测试组件节点渲染
在mock完相关的依赖之后,就可以对自身组件进行测试了
例如在Header中,我们需要测试是否渲染了一个Button
//Header.js <Button data-testid="button"> Button Context </Button>
//Header.test.js import {render} from '@testing-library/react'; renderHeader = render(<Header />); it('should show button', () => { expect(renderHeader.getByTestId('button')).toBeInTheDocument(); });
在这个测试中
render(<Header />)
是使用testing library的render方法渲染出Header组件renderHeader.getByTestId('button')
是testing library中的query方法,更多的query方法可以看这里但是,如果Header中并没有这个button的话,使用
getByTestId
会报错,这是因为在 testing library中的query方法中,所有的getBy方法都返回找到的第一个节点,并在没有匹配到或者匹配到多个时抛出error,这个时候就需要使用queryBy方法,即queryByTestIdqueryBy方法返回找到的第一个节点并在没有找到时返回null。
-
测试组件event
例如我们要测试点击Header组件中的button之后需要发生的事情,这个时候就需要模拟点击事件
fireEvent.click(renderHeader.getByTestId('button'));
更多的事件跳这里