深入理解Jest中的mock

对于异步函数的测试,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
发布了54 篇原创文章 · 获赞 22 · 访问量 7224

猜你喜欢

转载自blog.csdn.net/Riona_cheng/article/details/102468603