对于异步函数的测试,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