使用Jest模拟axios,不同接口返回不同数据

场景

在使用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'
    // 如果待测试组件只有一个请求需要模拟的情况:
    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官网

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享