Jest是 Facebook 的一套開源的 JavaScript 測試框架灭袁, 它自動集成了斷言杆烁、JSDom、覆蓋率報(bào)告等開發(fā)者所需要的所有測試工具简卧,是一款幾乎零配置的測試框架兔魂。并且它對同樣是 Facebook 的開源前端框架 React 的測試十分友好。
1. 全局安裝
yarn global add jest
或 npm install jest --global
這樣就可以通過命令行直接運(yùn)行Jest
yarn與npm對比
2. 結(jié)合babel使用jest
安裝所需的依賴:
yarn add --dev babel-jest @babel/core @babel/preset-env
還需安裝@babel/plugin-transform-runtime
举娩, @babel/runtime
析校,不然測試會報(bào)錯(cuò)
- .babelrc文件配置
可以在工程的根目錄下創(chuàng)建一個(gè)babel.config.js文件用于配置與你當(dāng)前Node版本兼容的Babel
{
"presets": [
["@babel/preset-env", {
"targets": {
"node": "current"
}
}]
],
"plugins": ["@babel/plugin-transform-runtime"]
}
- package.json配置
"jest": {
// moduleNameMapper: 一種正則表達(dá)式到模塊名的映射,匹配到的文件的內(nèi)容可以是空的
// 可以通過該參數(shù)铜涉,來mock一些圖片智玻,css等靜態(tài)資源文件
// 因?yàn)槲覀冊跍y試的時(shí)候?qū)嶋H上是不太需要這些文件的,但是有需要引入它作為環(huán)境上的依賴芙代。
"moduleNameMapper": {
"^vue$": "vue/dist/vue.common.js"
},
// moduleFileExtensions: 讓jest知道你需要測試覆蓋的文件的擴(kuò)展名都是什么吊奢。
"moduleFileExtensions": [
"js",
"vue"
],
// transform: 簡單來說就是轉(zhuǎn)換器,正則匹配到的文件可以通過對應(yīng)模塊的轉(zhuǎn)換器來解決一些未來版本語法時(shí)可以使用它纹烹。通過正則來匹配文件页滚,為匹配到的文件使用對應(yīng)的模塊
"transform": {
"^.+\\.js$": "<rootDir>/node_modules/babel-jest",
".*\\.(vue)$": "<rootDir>/node_modules/vue-jest"
}
}
注意: jest24不支持babel6
- 如要使用jest24,可以將babel升級到版本7
- 如果babel不能升級到7铺呵,那么就使用jest23
- babel不能升級到7裹驰,要使用jest24,那么就將babel-test版本鎖在23
3. 匹配器
常用匹配器:
- 普通匹配器: toBe, toEqual
- Truthiness: toBeNull片挂,toBeUndefined幻林,toBeDefined,toBeTruthy音念,toBeFalsy
- 數(shù)字: toBeGreaterThan沪饺,toBeGreaterThanOrEqual,toBeLessThan闷愤,toBeLessThanOrEqual整葡,toBeCloseTo
- 字符串:toMatch
- 數(shù)組:toContain
4. 測試用例
Jest會自動找到項(xiàng)目中所有使用.test.js文件命名的測試文件并執(zhí)行,通常我們在編寫測試文件時(shí)遵循的命名規(guī)范:測試文件的文件名 = 被測試模塊名 + .test.js肝谭,例如被測試模塊為functions.js掘宪,那么對應(yīng)的測試文件命名為functions.test.js蛾扇。
快照測試
只要想確保UI不會意外更改,快照測試是非常有用的工具魏滚。(其實(shí)就是運(yùn)行測試的時(shí)候镀首,把結(jié)果存一份,之后闊以用來對比鼠次,對比不上就測試不通過)
// Snapshot Testing
it('will fail every time', () => {
const user = {
createdAt: new Date(),
id: Math.floor(Math.random() * 20),
name: 'LeBron James',
}
// expect () 返回一個(gè)"期望"的對象
expect(user).toMatchSnapshot()
})
The first time this test is run, Jest creates a snapshot file that looks like this:
exports[`will fail every time 1`] = `
Object {
"createdAt": 2019-12-13T02:11:50.571Z,
"id": 1,
"name": "LeBron James",
}
`;
Jest使用pretty-format對快照文件進(jìn)行了處理更哄,當(dāng)代碼在審查期間,會讓代碼快照變成讓人類可閱讀的文件腥寇。
jest --updateSnapshot
更新快照
測試異步
單元測試的核心之一就是測試方法的行為是否符合預(yù)期成翩,在測試時(shí)要避免一切的依賴,將所有的依賴都mock掉
- 回調(diào):一種最常見的異步編程模式
錯(cuò)誤示例:
// 不要這么做赦役!
// 一旦 fetchData 執(zhí)行完畢麻敌,測試隨即完畢,而不會等待 callback 回調(diào)的執(zhí)行掂摔。
test('the data is peanut butter', () => {
function callback(data) {
expect(data).toBe('peanut butter')
}
fetchData(callback)
})
正確示例:
// 使用一個(gè)名為 done 的參數(shù)术羔,Jest 會一直等待 done 回調(diào)的執(zhí)行,一旦 done 回調(diào)執(zhí)行完畢乙漓,測試即完成级历。
// 如果 done 一直沒有被回調(diào),那么測試失敗叭披。
test('the data is peanut butter', done => {
function callback(data) {
expect(data).toBe('peanut butter');
done()
}
fetchData(callback)
})
- Promise
只需要在測試中返回一個(gè) promise寥殖,Jest 會自動等待 promise 被解析處理,如果 promise 被拒絕涩蜘,那么測試失敗嚼贡。
test('the data is peanut butter', () => {
// expect.assertions 來驗(yàn)證一定數(shù)量的斷言被調(diào)用。 否則一個(gè)fulfilled態(tài)的 Promise 不會讓測試失敗
expect.assertions(1)
return fetchData().then(data => {
expect(data).toBe('peanut butter');
})
})
test('the fetch fails with an error', () => {
expect.assertions(1);
return fetchData().catch(e => {
expect(e).toMatch('error')
})
})
5. 在webpack項(xiàng)目中用
- (1)如果你的項(xiàng)目使用了babel轉(zhuǎn)換皱坛,具體的配置编曼,參見上述第二個(gè)菜單
(2)如果你的項(xiàng)目沒有使用babel轉(zhuǎn)換,可以配置Jest的transform參數(shù)來進(jìn)行轉(zhuǎn)換 - 接下來剩辟,讓我們配置Jest,使其優(yōu)雅地處理資源文件往扔,如樣式表和圖像贩猎。 通常,這些文件在測試中無足輕重萍膛,因?yàn)槲覀兛梢园踩豰ock他們吭服。 然而, 如果你使用CSS模塊蝗罗,那么最好是給你的類名查找模擬一個(gè)代理艇棕。
// package.json
{
"jest": {
"moduleNameMapper": {
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/__mocks__/fileMock.js",
"\\.(css|less)$": "<rootDir>/__mocks__/styleMock.js"
}
}
}
6. 在react項(xiàng)目中使用
(1) 使用create react app:
它已經(jīng)包含了 可用的 Jest蝌戒! 您只需要添加react-test-renderer
來渲染快照。
yarn add --dev react-test-renderer
(2) 不使用create react app:
yarn add --dev jest babel-jest @babel/preset-env @babel/preset-react react-test-renderer
配置
// babel.config.js
module.exports = {
presets: ['@babel/preset-env', '@babel/preset-react'],
};