jest+vue-test-utils测试设置了lodash.debounce的函数

本文探讨如何在jest中测试使用lodash.debounce的Vue组件。主要介绍了两种成功方法:一是利用mockdate模拟时间,二是直接mock debounce为立即执行函数,确保内部接口正确调用。在尝试使用jest.runOnlyPendingTimers()时遇到问题,可能与lodash.debounce不兼容。
使用jest测试vue组件中设置了debounce的函数

代码中用到了lodash.debounce来避免一些高频操作导致的函数在短时间内被反复执行,需要测试函数中包含的接口及参数。待测试代码如下:

// MyVueComponent.vue
import _ from 'lodash'
getPrice: _.debounce(function() {
      myApi
        .calculateApi({
          params: {
            key1: value1
          },
          data: {
            params: {
              key2: value2
            }
          }
        })
        .then(response => {
          this.price = response.data.priceKey
        })
    }, 300)

需要测试下调用this.getPrice()函数的时候,myApi.calculateApi接口被正确调用。
踩了好多坑之后,有2种方法可测试成功。

1.借助mockdate插件,mock当前时间。

通过修改当前时间,达到定时设置时间,从而调用对应函数。

// MyVueComponent.spec.js
function getComponent(options = {}) {
  return shallowMount(
    MyVueComponent,
    extend(
      true,
      {
        propsData: {
          props1: value1 
        },
        store
      },
      options
    )
  )
}

let fakePriceApi
beforeAll(() => {
  fakeApi = jest.spyOn(myApi, 'calculateApi').mockResolvedValue({data: {result: {}}})
})
// MockDate is used to be change when now is.
import MockDate from 'mockdate'
function fastforward(time) {
  let now = Date.now() + time
  MockDate.set(now)
  jest.runTimersToTime(time)
}

describe('获取价格接口正确调用', () => {
  beforeEach(() => {
    jest.useFakeTimers()
  })
  afterEach(() => {
    jest.clearAllTimers()
  })
  it('影响价格的因素短时间内变化多次时,接口只会调用一次', () => {
    let wrapper = getComponent()
    wrapper.vm.getPrice()
    wrapper.vm.getPrice()
    wrapper.vm.getPrice()
    fastforward(50) // 第 50 ms时,接口未被调用
    expect(fakeApi).not.toHaveBeenCalled()
    fastforward(200) // 第 250 ms 时,接口被调用
    expect(fakeApi).toHaveBeenCalledTimes(1)
  })
  it('查询价格接口调用正确', () => {
    let wrapper = getComponent({
      propsData: {
        xxxx: 'aaaaa'
      }
    })
    wrapper.vm.getPrice()
    fastforward(250)    // 第 250 ms
    expect(fakeApi).toHaveBeenCalledWith(
      expect.objectContaining({
        params: {
          key1: value1
        },
        data: {
          params: expect.objectContaining({
            key2: value2
          })
        }
      })
    )
  })
})
2. 将debounce mock为立即执行的函数

不去验证getPrice是否会被debounce,因为debounce是第三方模块的方法,我们默认认为是正确的,我们要验证的是getPrice能够正确触发方法, 函数内部的接口能被正确调用即可。

// 通过mock将lodash的debounce修改为立即执行的函数
jest.mock('lodash/debounce', () => jest.fn(fn => fn))

只需添加一行mock代码,即可测试通过。

踩坑记录
  1. 方法1不使用mockdate,而是使用jest.runOnlyPendingTimers()。测试时,接口不能被成功调用。在查了许多资料后,这可能是lodash的debounce机制与jest的timer-mocks 无法兼容。

参考文献:

  • https://blog.youkuaiyun.com/duola8789/article/details/80434962
  • https://www.jianshu.com/p/c5d45306d374
  • https://blog.youkuaiyun.com/TMQ1225/article/details/81133855
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值