iT邦幫忙

2022 iThome 鐵人賽

DAY 28
0
自我挑戰組

web 應用開發筆記系列 第 28

[Day 28] Unit test

  • 分享至 

  • xImage
  •  

怎麼寫才算一個好的 Unit Test ?

測試應該可以在程式重構時發揮助益,如果在程式重構時一直修改寫好的測試,那麼這可能代表測試到不對的東西。

好的測試應該具備的特質

  • Easy to write
  • Readable
  • Reliable
  • Fast
  • Truly unit not integration

shallowMount vs mount ?

  • shallowMount 掛載一個組件而不渲染其子組件,渲染所有的子組件可能會讓我們的測試變慢
  • 建議只出现在snapshot中使用,凡能使用 shallowMount 的地方不用 mount
  • 當做 Unit Test 時,建議使用 shallowMount,需要元件互相搭配時,使用 mount。

Vue 異步處理

  • 默認情況下會異步地批量執行更新 (在下一輪 tick),以避免不必要的 DOM 重繪或者是觀察者計算
it('updates text', async () => {
  const wrapper = mount(Component)
  await wrapper.trigger('click')
  expect(wrapper.text()).toContain('updated')
  await wrapper.trigger('click')
  wrapper.text().toContain('some different text')
})

元件觸發 custom event

wrapper.vm.$emit('foo')
wrapper.vm.$emit('foo', 123)

/*
`wrapper.emitted()` 返回以下对象:
{
  foo: [[], [123]]
}
*/

判斷 custom evnt 是否如預期

// 断言事件已经被触发
expect(wrapper.emitted().foo).toBeTruthy()

// 断言事件的数量
expect(wrapper.emitted().foo.length).toBe(2)

// 断言事件的有效数据
expect(wrapper.emitted().foo[1]).toEqual([123])

Mock Browser API

  • 測試時通常不會備有 Browser API (不是運行在 browser 上)
export function setGlobals() {
  global.window.localStorage = {
    setItem: (key, value) => null,
    getItem: (key) => [],
  };
}

測試 DOM 元素是否如預期

test('has blah class', () => {
    expect(wrapper.contains('.blah')).toBe(true);
});

// check multiple elements by verifying count
test('has blah classes', () => {
    expect(wrapper.findAll('.blah').length).toBe(10);
});

** 注意: contain 預計未來會被官方淘汰,使用 find 或是 findComponent 較佳

test('has blah class', () => {
    expect(wrapper.find('.blah').exists()).toBe(true);
});

Mocking getters using computed Ref

Remember, this test is all about making sure the component behaves correctly given the current state of the store.

為了測試元件行為,我們需要偽造 vuex getter,若沒有 getter 則會噴以下錯誤

 [Vue warn]: Error in getter for watcher "selectedLabels": "TypeError: Cannot read property 'getters' of undefined"

在測試中增加 computed 來偽造 vuex getter 就可以正常執行

const wrapper = shallowMount(ClassMenu, {
  computed: {
    selectedModeClassListType: () => 'select',
    selectedLabels: () => [...],
  }
});

Deprecation warning

拿掉煩人的 Deprecation warning

import { config } from '@vue/test-utils';
config.showDeprecationWarnings = false;
Before

After

setup file

修正 [Vue warn]: Unknown custom element

package.json

  "jest": {
    "setupFiles": [
      "./src/specs/setup.js"
    ]
  }

上一篇
[Day 27] Building Landing Page Environment
下一篇
[Day 29] Vue with Jest
系列文
web 應用開發筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言