jest+vue-test-utils測試設置了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.csdn.net/duola8789/article/details/80434962
  • https://www.jianshu.com/p/c5d45306d374
  • https://blog.csdn.net/TMQ1225/article/details/81133855
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章