對於異步函數的測試,Jest中封裝了獨立的API,通過例子整理分類如下。
1.模擬請求
目錄結構:
|--demo.js
|--demo.test.js
|--package-lock.json
|--package.json
|--node_modules
|--.babelrc
業務代碼:demo.js
import axios from 'axios'
export const fetchData = () => {
return axios.get('/').then(res => res.data)
}
測試代碼:demo.test.js
import { fetchData } from './demo'
import Axios from 'axios'
jest.mock('axios') // 模擬axios
test('fetchData 測試', () => {
// 模擬請求
Axios.get.mockResolvedValue({
data: "(function(){return '123'})()"
})
return fetchData().then(data => {
expect(eval(data)).toEqual('123');
})
})
2.模擬demo
在根目錄下新建一個模擬文件夾,名字爲__mocks__,在__mocks__文件夾下新建demo.js文件。
|--__mocks__
|--demo.js
|--demo.js
|--demo.test.js
|--package-lock.json
|--package.json
|--node_modules
|--.babelrc
情景:當我們測試發送異步請求的代碼時,我們可以直接通過模擬demo的方式,測試請求方法是否正常執行.
demo.js
import axios from 'axios'
export const fetchData = () => {
// 發異步請求
return axios.get('/').then(res => res.data)
}
_ mocks _/demo.js
export const fetchData = () => {
// 做假請求
return new Promise((resolved, reject) => {
resolved("(function(){return '123'})()")
})
}
demo.test.js
jest.mock('./demo'); // 使用jest模擬demo,當執行測試用例時,就會去__mocks__文件下去找demo.js
import { fetchData } from './demo' // 通過jest模擬demo之後,再通過import引入fetchData
// 這裏引的fetchData是我們模擬的fetchData
test('fetchData 測試', () => {
return fetchData().then(data => {
expect(eval(data)).toEqual('123')
})
})
3.自動模擬設置
目錄結構和代碼同模擬demo一致。
通過修改jest.config.js配置,讓其自動模擬進行測試.
首先, 在命令行執行 npx jest --init 讓jest的配置文件暴露出來. 把配置文件中的自動模擬項(automock)設置爲true.
然後: 把demo.test.js文件中的 jest.mock(’./demo’) 刪除掉.
import { fetchData } from './demo'
test('fetchData 測試', () => {
return fetchData().then(data => {
expect(eval(data)).toEqual('123')
})
})
此時,再執行 npm test ,測試用例依然會通過。
注: 當我們把配置項 automock 修改爲 true 後,jest就會開啓自動模擬功能,就算測試文件中沒有聲明模擬代碼,jest依然會去自動查找根目錄中是否有mocks文件的存在,mocks文件夾下是否有相對應的demo.js文件。如果有,那麼在使用 import { fetchData } from ‘./demo’ 引入demo時,會拿mocks下的demo代替我們寫的業務代碼demo被引入。如果沒有,則會引入根目錄下得我們寫的業務文件demo。這就是自動模擬的運行機制。
4.異步函數模擬—同步函數不模擬
目錄結構:
|--__mocks__
|--demo.js
|--demo.js
|--demo.test.js
|--package-lock.json
|--package.json
|--node_modules
|--.babelrc
demo.js
import axios from 'axios'
// 異步函數
export const fetchData = () => {
// 發異步請求
return axios.get('/').then(res => res.data)
}
// 同步函數
export const getNumber = () => {
return 123;
}
demo.test.js
jest.mock('./demo'); // 使用jest模擬demo,當執行測試用例時,就會去__mocks__文件下去找demo.js
import { fetchData } from './demo'; // 通過jest模擬demo,這裏的fetchData是來自於模擬的demo裏的
const { getNumber } = jest.requireActual('./demo'); // 這裏的getNumber是來自於真正的demo裏的
test('fetchData 測試', () => {
return fetchData().then(data => {
expect(eval(data)).toEqual('123');
})
})
test('getNumber 測試', () => {
expect(getNumber()).toBe(123);
})
- jest.requireActual(’./demo’) 引入真正的業務代碼文件。(不是通過jest模擬的)
- 對異步函數模擬、對同步函數不模擬,這樣既可實現同步函數 和 異步函數的完美測試。
取消模擬
jest.unmock('./demo'); // 取消模擬demo
jest.unmock('axios'); // 取消模擬axios