场景
在使用Jest时,会遇到比如某个页面可能使用axios调用了多个后端接口数据。我们可能会有针对不同接口模拟返回不同数据的需求,本文主要总结这种场景下的解决方案。
基础Api
-
模拟模块:
jest.mock(moduleName, factory, options)- 参数
moduleName:模拟的模块
// banana.js module.exports = () => 'banana' // __test__/test.js const banana = require('./banana') jest.mock('./banana') banana() // 默认返回undefined- 参数
factory: 自定义模拟模块的执行函数,比如自定义执行函数后指定返回值;如果未选,jest.mock默认模块执行后返回值为undefined。需要注意的是,模拟ES6模块时,需要手动指定__esModule: true,默认导出moduleName需要指定为default属性
// __test__/test.js import moduleName, {foo} from '../moduleName' jest.mock('../moduleName', () => { return { __esModule: true, default: jest.fn(() => 42), foo: jest.fn(() => 43), } }) moduleName() // 42 foo() // 43- 参数
options: 用于创建虚拟模拟,用的比较少
- 参数
-
模拟函数一:
jest.fn(implementation),返回一个新的模拟函数mock function,所以支持链式调用,如jest.fn().mockImplementation(() => true)- 参数
implementation: 自定义执行函数
// __test__/test.js const mockFn = jest.fn() mockFn() // undefined expect(mockFn).toHaveBeenCalled() // 自定义执行函数 const mockFn = jest.fn(() => true) // 等价于 jest.fn().mockImplementation(() => true) mockFn() // true - 参数
-
模拟函数二:
jest.fn().mockResolvedValue(response)等同于jest.fn().mockImplementation(() => Promise.resolve(response))
代码实现
// __test__/test.js
import axios from 'axios'
jest.mock('axios')
// 如果待测试组件只有一个请求需要模拟的情况:
const response = { // 需要注意的是模拟返回的数据需要与真实接口返回数据结构一致,否则组件可能无法使用模拟数据正常渲染,达到我们想要的结果
code: '000000',
msg: 'ok',
data: {
...
}
}
axios.get.mockResolvedValue(response)
// 如果待测试组件有多个不同请求,先定义好不同的返回结果:
const response1 = {
code: '000000',
msg: 'ok',
data: {
...
}
}
const response2 = {
code: '000000',
msg: 'ok',
data: {
...
}
}
...
// 根据不同请求方法返回不同的response
axios.get.mockResolvedValue(response1)
axios.post.mockResolvedValue(response2)
axios.patch.mockResolvedValue(response3)
...
// 如果请求方式都一致,可通过url再细分,返回不同的response
axios.get.mockImplementation(url => {
switch (url) {
case '/url-1':
return Promise.resolve(response1)
case '/url-2':
return Promise.resolve(response2)
...
}
})
总结
jest.mock('axios')相当于使用jest.fn()代理了axios模块内的所有(get/post/patch等)方法jest.fn().mockResolvedValue(response)是jest.fn().mockImplementation(() => Promise.resolve(response))的语法糖函数,可结合async...await使用- 不同的请求方法可直接根据请求方法区分返回指定
response;相同请求方法不同url可根据axios.post.mockImplementation(url => ...)参数url区分,返回指定response
参考
与jest.fn()类似的方法还有jest.spyOn(object, methodName),具体参考官方文档
Jest官网