一、渲染: mount 和 shallowMount
1.1 mount 和 shallowMount
vue-test-utils
提供了兩種方式用于渲染,或者說 加載(mount) 一個(gè)組件 — mount
和 shallowMount
。一個(gè)組件無論使用這兩種方法的哪個(gè)都會(huì)返回一個(gè) wrapper
,也就是一個(gè)包含了 Vue 組件
的對(duì)象,輔以一些對(duì)測(cè)試有用的方法。
1.2 mount 和 shallowMount的區(qū)別
-
mount
: 會(huì)渲染子組件 -
shallowMount
:會(huì)加載子組件,不會(huì)被子組件的行為屬性影響該組件
二、 beforeEach 和beforeAll
2.1 為多次測(cè)試重復(fù)設(shè)置
如果你有一些要為多次測(cè)試重復(fù)設(shè)置的工作,可以使用beforeEach和afterEach。
有這樣一個(gè)需求,需要我們?cè)诿總€(gè)測(cè)試之前調(diào)用方法initializeCityDatabase(),在每個(gè)測(cè)試后,調(diào)用方法clearCityDatabase()
beforeEach(() => {
initializeCityDatabase();
});
afterEach(() => {
clearCityDatabase();
});
test('city database has Vienna', () => {
expect(isCity('Vienna')).toBeTruthy();
});
test('city database has San Juan', () => {
expect(isCity('San Juan')).toBeTruthy();
});
2.2 一次性設(shè)置
在某些情況下,你只需要在文件的開頭做一次設(shè)置。這種設(shè)置是異步行為的時(shí)候,你不太可能一行處理它。Jest提供了beforeAll和afterAll處理這種情況。
beforeAll(() => {
return initializeCityDatabase();
});
afterAll(() => {
return clearCityDatabase();
});
test('city database has Vienna', () => {
expect(isCity('Vienna')).toBeTruthy();
});
test('city database has San Juan', () => {
expect(isCity('San Juan')).toBeTruthy();
});
2.3 作用域
默認(rèn)情況下,before和after的塊可以應(yīng)用到文件中的每一個(gè)測(cè)試。此外可以通過describe塊來將將測(cè)試中的某一塊進(jìn)行分組。當(dāng)before和after的塊在describe塊內(nèi)部的時(shí)候,則只適用于該describe塊內(nèi)的測(cè)試。
三、匹配器
3.1 匹配器基礎(chǔ)
-
toBe
:判斷是否相等 -
toBeNull
:判斷是否為null -
toBeUndefined
:判斷是否為undefined -
toBeDefined
:與上相反 -
toBeNaN
:判斷是否為NaN -
toBeTruthy
:判斷是否為true -
toBeFalsy
:判斷是否為false -
toContain
:數(shù)組用,檢測(cè)是否包含 -
toHaveLength
:數(shù)組用,檢測(cè)數(shù)組長(zhǎng)度 -
toEqual
:對(duì)象用,檢測(cè)是否相等 -
toStrictEqual
:功能與 toEqual 相似,但是更加嚴(yán)格 -
toThrow
:異常匹配 -
toBeCalled
: 函數(shù)是否被調(diào)用 -
toHaveBeenCalledTimes
: 函數(shù)被調(diào)用幾次 -
expect.assertions(n)
: 表示必須執(zhí)行n次expect 代碼才算執(zhí)行完
3.2 匹配器使用
describe('Test', () => {
// 判斷是否相等
expect(2 + 2).toBe(4);
// 判斷是否為null
expect(null).toBeNull();
// 判斷是否為undefined
expect(undefined).toBeUndefined();
let a = 1;
// 判斷是否不為undefined
expect(a).toBeDefined();
a = 'ada';
// 判斷是否為NaN
expect(a).toBeNaN();
a = true;
// 判斷是否為true
expect(a).toBeTruthy();
a = false;
// 判斷是否為false
expect(a).toBeFalsy();
a = [1, 2, 3];
// 數(shù)組用,檢測(cè)是否包含
expect(a).toContain(2);
// 數(shù)組用,檢測(cè)數(shù)組長(zhǎng)度
expect(a).toHaveLength(3);
a = { a: 1 };
// 對(duì)象用,檢測(cè)是否相等
expect(a).toEqual({ a: 1 });
// 功能與 toEqual 相似,但是更加嚴(yán)格
expect(a).toStrictEqual({ a: 1 });
a = () => 1;
// 函數(shù)是否被調(diào)用
expect(a).toBeCalled();
// 函數(shù)被調(diào)用幾次
expect(a).toHaveBeenCalledTimes(1);
});
3.3 toStrictEqual 與 toEqual 的區(qū)別
toStrictEqual 的功能與 toEqual 相似,但是更加嚴(yán)格。主要體現(xiàn)在:
- 即使兩個(gè)對(duì)象的成員相同,但原型鏈不同則不同。
- undefined 和未定義不兼容。
3.4 expect.assertions(number)
驗(yàn)證在測(cè)試期間調(diào)用了一定數(shù)量的斷言,在測(cè)試異步代碼時(shí)這通常很有用,以便確?;卣{(diào)中的斷言確實(shí)被調(diào)用。
假設(shè)我們有一個(gè)函數(shù)doAsync,它接收兩個(gè)回調(diào)callback1和callback2,它將異步地以一個(gè)未知的順序調(diào)用它們。
test('doAsync calls both callbacks', () => {
expect.assertions(2);
function callback1(data) {
expect(data).toBeTruthy();
}
function callback2(data) {
expect(data).toBeTruthy();
}
doAsync(callback1, callback2);
});
四、Wrapper
-
Wrapper
:Wrapper 是一個(gè)包括了一個(gè)掛載組件或 vnode,以及測(cè)試該組件或 vnode 的方法。 -
Wrapper.vm
:這是該 Vue 實(shí)例。你可以通過 wrapper.vm 訪問一個(gè)實(shí)例所有的方法和屬性。 -
Wrapper.classes
:返回是否擁有該class的dom或者類名數(shù)組。 -
Wrapper.find
:返回第一個(gè)滿足條件的dom。 -
Wrapper.findAll
:返回所有滿足條件的dom。 -
Wrapper.html
:返回html字符串。 -
Wrapper.text
:返回內(nèi)容字符串。 -
Wrapper.setData
:設(shè)置該組件的初始data數(shù)據(jù)。 -
Wrapper.setProps
:設(shè)置該組件的初始props數(shù)據(jù)。 -
Wrapper.trigger
:用來觸發(fā)事件。
五、模擬函數(shù)
5.1 模擬函數(shù)
-
jest.fn()
:生成一個(gè)模擬函數(shù),這個(gè)函數(shù)可以用來代替源代碼中被使用的第三方函數(shù) -
mockFn.mockImplementation(fn)
:接受一個(gè)函數(shù),該函數(shù)應(yīng)用作模擬的實(shí)現(xiàn) -
mockFn.mockImplementationOnce(fn)
:接受一個(gè)函數(shù),該函數(shù)將用作對(duì)被模擬函數(shù)的一次調(diào)用的模擬實(shí)現(xiàn) -
mockFn.mockReturnValue(value)
:用于定義在指定函數(shù)的每一次調(diào)用時(shí)返回預(yù)設(shè)值 -
mockFn.mockReturnValueOnce(value)
: -
mockFn.mockResolvedValue(value)
:用于定義在指定異步
函數(shù)的每一次調(diào)用時(shí)返回預(yù)設(shè)值 -
mockFn.mockResolvedValueOnce(value)
:
5.2 mockImplementationOnce()
const myMockFn = jest.fn(() => 'default')
.mockImplementationOnce(() => 'first call')
.mockImplementationOnce(() => 'second call');
console.log(myMockFn(), myMockFn(), myMockFn(), myMockFn());
// 'first call', 'second call', 'default', 'default'
六、mock系統(tǒng)
6.1 常用的mock方法
在單元測(cè)試中,很多時(shí)候不想因?yàn)橥ㄟ^測(cè)試而改變?cè)瓉淼拇a邏輯或者只是想簡(jiǎn)單地獲取一個(gè)數(shù)據(jù)來順利進(jìn)行測(cè)試,這個(gè)時(shí)候就需要手動(dòng)mock數(shù)據(jù),Jest提供了一個(gè)強(qiáng)大的mock系統(tǒng)。在全局的Jest對(duì)象里,有三個(gè)常用的mock方法:
-
jest.fn(implementation)
:返回一個(gè)mock函數(shù),其中implementation 為可選,代表mock函數(shù)的模擬實(shí)現(xiàn)。 -
jest.mock(moduleName, factory, options)
:用來mock一些模塊或者文件。 -
jest.spyOn(object, methodName)
:返回一個(gè)mock函數(shù),和jest.fn相似,但是能夠追蹤object[methodName]的調(diào)用信息,如果object[methodName]不是一個(gè)函數(shù),則會(huì)報(bào)錯(cuò)。
6.2 jest.fn()
Jest.fn()是創(chuàng)建Mock函數(shù)最簡(jiǎn)單的方式,如果沒有定義函數(shù)內(nèi)部的實(shí)現(xiàn),jest.fn()會(huì)返回undefined作為返回值。
Jest.fn()所創(chuàng)建的Mock函數(shù)還可以設(shè)置返回值,定義內(nèi)部實(shí)現(xiàn)或返回Promise對(duì)象。
6.3 jest.mock()
6.3.1 使用 jest.mock 自動(dòng) mock
jest.mock('./utils.ts')
自動(dòng)返回一個(gè) mock ,可以使用它來監(jiān)視對(duì)類構(gòu)造函數(shù)及其所有方法
的調(diào)用。
6.3.2 jest.mock()直接在單元測(cè)試?yán)锩鎚ock 模塊
jest.mock(path, moduleFactory)
接受模塊工廠參數(shù)。模塊工廠是一個(gè)返回模擬的函數(shù)。為了模擬構(gòu)造函數(shù),模塊工廠必須返回構(gòu)造函數(shù)。換句話說,模塊工廠必須是返回函數(shù)的函數(shù)-高階函數(shù)(HOF)。
jest.mock('fs', () => ({
readFileSync: jest.fn()
}))
6.3.3 在需要mock的模塊目錄臨近建立目錄__mocks__
6.3.4 樣例
// utils.js
export default {
add(a, b) {
console.log('---------------util.js add----------');
return a + b;
}
};
// mock.js
import utils from './utils';
export default {
test() {
console.log('---------------mock.js test----------');
return utils.add(1, 2);
}
};
// mock.test.js
import m from './mock';
import utils from './utils';
jest.mock('./utils.js');
it('mock 整個(gè) fetch.js模塊', () => {
m.test();
expect(utils.add).toBeCalledTimes(1);
});
6.4 jest.spyOn()
jest.spyOn()方法同樣創(chuàng)建一個(gè)mock函數(shù),但是該mock函數(shù)不僅能夠捕獲函數(shù)的調(diào)用情況,還可以正常的執(zhí)行被spy的函數(shù)。實(shí)際上,jest.spyOn()是jest.fn()的語法糖,它創(chuàng)建了一個(gè)和被spy的函數(shù)具有相同內(nèi)部代碼的mock函數(shù)。
import m from './mock';
import utils from './utils';
it('mock 整個(gè) fetch.js模塊', () => {
const y = jest.spyOn(utils, 'add');
m.test();
expect(y).toBeCalledTimes(1);
});
- 使用
jest.mock()
時(shí)add方法實(shí)際沒有執(zhí)行
,使用jest.spyOn()
時(shí)add會(huì)被執(zhí)行
七、wrapper.emitted()
每個(gè)掛載的包裹器都會(huì)通過其背后的 Vue 實(shí)例自動(dòng)記錄所有被觸發(fā)的事件。你可以用 wrapper.emitted() 方法取回這些事件記錄。文章來源:http://www.zghlxwxcb.cn/news/detail-450674.html
wrapper.vm.$emit('foo')
wrapper.vm.$emit('foo', 123)
/*
`wrapper.emitted()` 返回以下對(duì)象:
{
foo: [[], [123]]
}
*/
// 斷言事件已經(jīng)被觸發(fā)
expect(wrapper.emitted().foo).toBeTruthy()
// 斷言事件的數(shù)量
expect(wrapper.emitted().foo.length).toBe(2)
// 斷言事件的有效數(shù)據(jù)
expect(wrapper.emitted().foo[1]).toEqual([123])
你也可以調(diào)用 wrapper.emittedByOrder() 獲取一個(gè)按觸發(fā)先后排序的事件數(shù)組。文章來源地址http://www.zghlxwxcb.cn/news/detail-450674.html
參考
- Vue測(cè)試指南(vue.js 2)
- vue中如何使用jest單元測(cè)試
- jest beforeEach 和beforeAll區(qū)別
- Jest 配置與 React Hook 單元測(cè)試教程
- jest手冊(cè)
- Jest 使用指南 - - Mock 篇
- 【測(cè)試學(xué)習(xí)】UI測(cè)試工具vue-test-utils入門教程
- Vue 應(yīng)用測(cè)試
到了這里,關(guān)于vue jest單元測(cè)試的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!