日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 前端技术 > vue >内容正文

vue

testid oracle vue,Vue 组件单元测试究竟测试什么?

發(fā)布時(shí)間:2024/4/20 vue 77 豆豆
生活随笔 收集整理的這篇文章主要介紹了 testid oracle vue,Vue 组件单元测试究竟测试什么? 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

關(guān)于 Vue 組件單元測(cè)試最常見(jiàn)的問(wèn)題就是“我究竟應(yīng)該測(cè)試什么?”

雖然測(cè)試過(guò)多或過(guò)少都是可能的,但我的觀察是,開(kāi)發(fā)人員通常會(huì)測(cè)試過(guò)頭。畢竟,沒(méi)有人愿意自己的組件未經(jīng)測(cè)試從而導(dǎo)致應(yīng)用程序在生產(chǎn)中崩潰。

在本文中,我將分享一些用于組件單元測(cè)試的指導(dǎo)原則,這些指導(dǎo)原則可以確保在編寫測(cè)試上不會(huì)花費(fèi)大量時(shí)間,但是可以提供足夠的覆蓋率來(lái)避免錯(cuò)誤。

本文假設(shè)你已經(jīng)了解 Jest 和 Vue Test Utils。

示例組件

在學(xué)習(xí)這些指導(dǎo)原則之前,我們先來(lái)熟悉下要測(cè)試的示例組件。組件名為Item.vue?,是 eCommerce App 里的一個(gè)產(chǎn)品條目。

下面是組件的源碼。注意有三個(gè)依賴項(xiàng):Vuex ($store), Vue Router ($router) 和 Vue Auth ($auth)。

Item.vue

{{ item.title }}

Add To Cart

export default {

name: "Item",

props: [ "id" ],

computed: {

item () {

return this.$store.state.find(

item => item.id === this.id

);

}

},

methods: {

addToCart () {

if (this.$auth.check()) {

this.$store.commit("ADD_TO_CART", this.id);

} else {

this.$router.push({ name: "login" });

}

}

}

};

復(fù)制代碼

配置 Spec 文件

下面是測(cè)試用的 spec 文件。其中,我們將用 Vue Test Utils “淺掛載”示例組件,因此引入了相關(guān)模塊以及我們要測(cè)試的 Item 組件。

同時(shí)還寫了一個(gè)工廠函數(shù)用于生成可覆蓋的配置對(duì)象,以免在每個(gè)測(cè)試中都需要指定 props 和 mock 三個(gè)依賴項(xiàng)。

item.spec.js

import { shallowMount } from "@vue/test-utils";

import Item from "@/components/Item";

function createConfig (overrides) {

const id = 1;

const mocks = {

// Vue Auth

$auth: {

check: () => false

},

// Vue Router

$router: {

push: () => {}

},

// Vuex

$store: {

state: [ { id } ],

commit: () => {}

}

};

const propsData = { id };

return Object.assign({ mocks, propsData }, overrides);

}

describe("Item.vue", () => {

// Tests go here

});

復(fù)制代碼

確定業(yè)務(wù)邏輯

對(duì)于要測(cè)試的組件,要問(wèn)的第一個(gè)也是最重要的問(wèn)題是“業(yè)務(wù)邏輯是什么”,即組件是做什么的?

對(duì)于這個(gè)Item.vue,業(yè)務(wù)邏輯是:

根據(jù)接收的id屬性展示條目信息

如果用戶是訪客,點(diǎn)擊?Add to Cart?按鈕將重定向到登錄頁(yè)

如果用戶已登錄,點(diǎn)擊?Add to Cart?按鈕會(huì)觸發(fā) Vuex mutation ?ADD_TO_CART。

確定輸入和輸出

當(dāng)你對(duì)組件做單元測(cè)試時(shí),可將其視為一個(gè)黑盒。方法、計(jì)算屬性等內(nèi)部邏輯只影響輸出。

因此,下一個(gè)重點(diǎn)是確定組件的輸入和輸出,因?yàn)檫@些也是測(cè)試的輸入和輸出。

Item.vue 的輸入是:

id?屬性

來(lái)自 Vuex 和 Vue Auth 的數(shù)據(jù)狀態(tài)

用戶點(diǎn)擊按鈕

輸出是:

渲染后的 HTML

發(fā)送到 Vuex mutation 或者 Vue Router push 的數(shù)據(jù)

有些組件也會(huì)將表單和事件作為輸入,觸發(fā)事件作為輸出。

測(cè)試 1: 訪客點(diǎn)擊按鈕跳轉(zhuǎn)路由

有一個(gè)業(yè)務(wù)邏輯是“如果用戶是訪客,點(diǎn)擊?Add to Cart 按鈕將重定向到登錄頁(yè)”。我們來(lái)寫這個(gè)測(cè)試。

我們通過(guò)“shallow mount”組件來(lái)編寫測(cè)試,然后找到并點(diǎn)擊Add to Cart?按鈕。

test("router called when guest clicks button", () => {

const config = createConfig();

const wrapper = shallowMount(Item, config);

wrapper

.find("button")

.trigger("click");

// Assertion goes here

}

復(fù)制代碼

隨后我們會(huì)加上 assertion。

不要超出輸入和輸出的界限

在這個(gè)測(cè)試中很容易采取的做法是在點(diǎn)擊按鈕后判斷路由是否跳轉(zhuǎn)到了登錄頁(yè),比如:

import router from "router";

test("router called when guest clicks button", () => {

...

// 錯(cuò)!

const route = router.find(route => route.name === "login");

expect(wrapper.vm.$route.path).toBe(route.path);

}

復(fù)制代碼

雖然這確實(shí)也能測(cè)試組件的輸出,但是它依賴于路由功能,這不應(yīng)該是組件所關(guān)心的。

直接測(cè)試組件的輸出會(huì)更好,也就是調(diào)用了?$router.push。至于路由是否最終完成了操作,這已經(jīng)超出了本測(cè)試的范疇。

因此我們可以監(jiān)聽(tīng)路由的?push?方法,并斷言它是否被登錄路由對(duì)象調(diào)用。

import router from "router";

test("router called when guest clicks button", () => {

...

jest.spyOn(config.mocks.$router, "push");

const route = router.find(route => route.name === "login");

expect(spy).toHaveBeenCalledWith(route);

}

復(fù)制代碼

測(cè)試 2: 登錄用戶點(diǎn)擊按鈕后調(diào)用 vuex

接下來(lái)讓我們測(cè)試業(yè)務(wù)邏輯“如果用戶已登錄,點(diǎn)擊?Add to Cart?按鈕將觸發(fā) Vuex mutation ADD_TO_CART”。

同樣,你不需要判斷 Vuex 狀態(tài)是否更改了。要驗(yàn)證這個(gè)需要另外單獨(dú)測(cè)試 Vuex store。

組件的職責(zé)只是執(zhí)行 commit,因此我們只要測(cè)試這個(gè)動(dòng)作就行。

首先重寫?$auth.check?假數(shù)據(jù)讓它返回?true?(模擬登錄用戶)。然后監(jiān)聽(tīng) store 的?commit?方法,并斷言點(diǎn)擊按鈕后被調(diào)用。

test("vuex called when auth user clicks button", () => {

const config = createConfig({

mocks: {

$auth: {

check: () => true

}

}

});

const spy = jest.spyOn(config.mocks.$store, "commit");

const wrapper = shallowMount(Item, config);

wrapper

.find("button")

.trigger("click");

expect(spy).toHaveBeenCalled();

}

復(fù)制代碼

不要測(cè)試其他庫(kù)的功能

Item 組件展示條目數(shù)據(jù),特別是標(biāo)題和圖片。或許我們應(yīng)該寫一個(gè)測(cè)試來(lái)專門檢查這些?比如:

test("renders correctly", () => {

const wrapper = shallowMount(Item, createConfig());

// Wrong

expect(wrapper.find("h2").text()).toBe(item.title);

}

復(fù)制代碼

這又是一個(gè)不必要的測(cè)試,因?yàn)樗皇菧y(cè)試了 Vue 從 Vuex 中提取數(shù)據(jù)并插入到模板的能力。Vue 這個(gè)庫(kù)已經(jīng)對(duì)該機(jī)制進(jìn)行了測(cè)試,所以你應(yīng)該依賴于它。

測(cè)試 3: 正確地渲染

但是等等,如果有人不小心將title重命名為name,然后忘記更新插值表達(dá)式怎么辦?這難道不需要測(cè)試嗎?

沒(méi)錯(cuò),但是如果你像這樣來(lái)測(cè)試模板的方方面面,何時(shí)才是個(gè)頭?

測(cè)試 HTML 最好的辦法是使用快照,用來(lái)檢查整體渲染后的結(jié)果。這不僅覆蓋了標(biāo)題插值,還包括圖片、按鈕文本、任何 class 等。

test("renders correctly", () => {

const wrapper = shallowMount(Item, createConfig());

expect(wrapper).toMatchSnapshot();

});

復(fù)制代碼

其他不需要測(cè)試的點(diǎn)還有這些:

src?屬性是否綁定到 img 元素

添加到 Vuex store 中的數(shù)據(jù)是否跟插入的數(shù)據(jù)一致

計(jì)算屬性是否返回了正確的數(shù)據(jù)

執(zhí)行 router push 是否重定向到正確的頁(yè)面

諸如此類。

總結(jié)

我認(rèn)為上面三個(gè)簡(jiǎn)單的測(cè)試對(duì)這個(gè)組件來(lái)說(shuō)足夠了。

組件單元測(cè)試的一個(gè)好理念是先假設(shè)測(cè)試是不必要的,除非被證明是必要的。

你可以問(wèn)自己以下問(wèn)題:

這是業(yè)務(wù)邏輯的一部分嗎?

這是直接測(cè)試組件的輸入和輸出嗎?

這是測(cè)試自己的代碼,還是第三方代碼?

讓我們愉快地單元測(cè)試吧!

更多前端技術(shù)干貨盡在微信公眾號(hào):1024譯站

總結(jié)

以上是生活随笔為你收集整理的testid oracle vue,Vue 组件单元测试究竟测试什么?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。