jest函數單元測試


一、總體概念

jest單元測試的寫法為三步,引入測試內容,運行測試內容,最后進行比較,是否達到預期。

Jest中的斷言使用expect, 它接受一個參數,就是運行測試內容的結果,返回一個對象,這個對象來調用匹配器(toBe/。。。。) ,

匹配器的參數就是我們的預期結果,這樣就可以對結果和預期進行對比了,也就可以判斷對不對了

1、兩個必會的方法

  • test方法:Jest封裝的測試方法,一般填寫兩個參數,描述和測試方法

  • expect方法 :預期方法,就是你調用了什么方法,傳遞了什么參數,得到的預期是什么

2、匹配器:

  1. toBe():絕對相等(===)
  2. toEqual():簡單類型絕對匹配;復雜類型內容結果的匹配
  3. toBeNull():匹配null
  4. toBeUndefined():匹配undefined
  5. toBeDefined():匹配非undefined
  6. toBeTruthy():匹配轉化后為true
  7. toBeFalsy():匹配轉化后為false
  8. toBeGreaterThan():相當於大於號
  9. toBeLessThan():相當於小於號
  10. toBeGreaterThanOrEqual():相當於大於等於號
  11. toBeLessThanOrEqual():相當於大於等於號
  12. toBeCloseTo():解決js浮點錯誤
  13. toMatch(regExp/string):用正則表達式或者字符串匹配字符串片段
  14. toContain():匹配數組或者Set中的某一項
  15. toThrow():匹配異常處理,如果拋出了異常就過測試用例
expect({a:1}).toBe({a:1})//判斷兩個對象是否相等
expect(1).not.toBe(2)//判斷不等
expect(n).toBeNull(); //判斷是否為null
expect(n).toBeUndefined(); //判斷是否為undefined
expect(n).toBeDefined(); //判斷結果與toBeUndefined相反
expect(n).toBeTruthy(); //判斷結果為true
expect(n).toBeFalsy(); //判斷結果為false
expect(value).toBeGreaterThan(3); //大於3
expect(value).toBeGreaterThanOrEqual(3.5); //大於等於3.5
expect(value).toBeLessThan(5); //小於5
expect(value).toBeLessThanOrEqual(4.5); //小於等於4.5
expect(value).toBeCloseTo(0.3); // 浮點數判斷相等
expect('Christoph').toMatch(/stop/); //正則表達式判斷
expect(['one','two']).toContain('one'); //匹配數組

function compileAndroidCode() {
  throw new ConfigError('you are using the wrong JDK');
}

test('compiling android goes as expected', () => {
  expect(compileAndroidCode).toThrow();
  expect(compileAndroidCode).toThrow(ConfigError); //判斷拋出異常
})

 3、describe()測試分組

Jest為我們提供了一個分組的語法describe(),創建一個測試集。

這個方法接受兩個參數,它的語法和test 的一致,第一個參數也是字符串,對這一組測試進行描述, 第二個參數是一個函數,函數體就是一個個的test 測試。

在jest中,test和it一樣,接受兩個參數,第一個是字符串,對這個測試進行描述,需要什么條件,達到什么效果。第二個是函數,函數體就是真正的測試代碼,jest 要執行的代碼

 對一個功能進行測試,但它分為多種情況,需要多個test或it, 最好使用descibe() 把多個test 包起來,形成一組測試。只有這一組都測試完成之后,才能說明這個功能是好的。

import {isTrueOrFasle} form './tools' ; 
describe('true or false', () => {  it('should return true when input true', () => { let result = isTrueOrFasle(true); expect(result).toBeTruthy(); // toBeTruthy 匹配器  }) test('should return false when input fasle', () => { let result = isTrueOrFasle(false); expect(result).toBeFalsy();  // toBeFalsy 匹配器  }) })

4、異步代碼測試

回調函數/promise/asyn await
參考:https://www.cnblogs.com/SamWeb/p/11454923.html

expect.assertions(1); //斷言,表示必須執行一次expect 代碼才算執行完

test('test axios async await', async() => {
    const res = await fetchThreeData();
    expect(res.data).toEqual({
        success: true
    })
})

5、Mock函數

 有時進行單元測試時,要測試的內容依賴其他內容,比如異步請求,會依賴網絡,很可能造成測試達不到效果。 能不能把依賴變成可控的內容?這就用到Mock。Mock就是把依賴替換成我們可控的內容,實現測試的內容和它的依賴項隔離。那怎么才能實現mock呢?使用Mock 函數。在jest中,當我們談論Mock的時候,其實談論的就是使用Mock 函數代替依賴。Mock函數就是一個虛擬的或假的函數,所以對它來說,最重要的就是實現依賴的全部功能,從而起到替換的作用。通常,mock函數會提供以下三個功能,來實現替換:函數的調用捕獲,設置函數返回值,改變原函數的實現。

在jest 創建一個Mock 函數最簡單的方法就是調用jest.fn() 方法。

1.函數的調用捕獲。捕獲調用指的是這個函數有沒有被調用,調用的參數是什么,返回值是什么,通常用於測試回調函數,模擬真實的回調函數。就像下邊的forEachFun函數,它接受一個回調函數,每個調用者都會傳遞不同的回調函數過來,我們事先並不知道回調函數,再者我們測試forEach 的重點是,該函數是不是把數組中的每一項都傳遞給回調函數了,所以回調函數只要是一個函數就可以了,但該函數必須把調用的信息都保存下來,這就是Mock 函數的調用捕獲,為此mock 函數還有一個mock 屬性。

測試中就使用jest.fn() 生成的mock 函數來模擬真實的回調函數。

// mock的第一個用處:調用函數的捕獲
export const forEachFun = (array: any[], callback: Function) => {
  array.forEach((i) => callback(i));
};

test('should call callback everyone', () => {
  const mockFun = jest.fn(); // 模擬函數
  const testArr = [1, 2];
  forEachFun(testArr, mockFun);
  console.log(30, mockFun.mock);
  expect(mockFun.mock.calls.length).toBe(2);
});

mock函數mockFun的mock 屬性是一個對象,打印結果:

{
  calls: [ [ 1 ], [ 2 ] ],   instances: [ undefined, undefined ],   invocationCallOrder: [ 1, 2 ],   results:[
        { type:
'return', value: undefined },         { type: 'return', value: undefined }
  ]
}
  •  calls 保存的就是調用狀態。calls 是一個數組,每一次的調用都組成數組的一個元素,在這里調用了兩次,就有兩個元素。每一個元素又是一個數組,它則表示的是函數調用時的參數,因為每次的調用都傳遞了一個參數給函數,所以數組只有一項。如果有多個參數,數組就有多項,按照函數中的參數列表依次排列。這時候,就可以做斷言,函數調用了幾次,就判斷calls.length. expect(mockFun.mock.calls.length).toBe(2) 就是斷言函數是不是調用了兩次。expcet(mockFun.mock.calls[0][0]) .toBe(1)就是斷言第一次調用的時候傳遞的參數是不是1. 可能覺得麻煩了, 的確有點麻煩了,幸好,jest 對函數的mock參數進行了簡單的封裝,提供了簡單的匹配器

   toHaveBeenCalled()/toBeCalled():用來判斷mock函數是否被掉用過;

   toHaveBeenCalledTimes(number)/toBeCalledTimes(number):用來判斷mock函數調用過幾次;

   toHaveBeenCalledWith(arg1,arg2,...)/toBeCalledWith(arg1,arg2,...):用來判斷是否使用了特定參數調mock函數

   ..... 參考官網

test('should call callback everyone', () => { const mockFun = jest.fn(); const testArr = [1, 2]; forEachFun(testArr, mockFun); expect(mockFun).toHaveBeenCalled(); });
  • results保存的就是返回值。

2.設置函數返回值。有的時候,不想調用函數,直接獲取到函數的返回值就可以了,比如異步函數, 以fetchData 為例,它直接返回一個promise 就好了,根本沒有必要請求服務器。

mock函數有mockReturnValue(),  它的參數就是返回值。不過它不能返回promise.。

可以使用mockResolvedValue直接返回promise的值. 對fetchData 進行mock, 然后設置它的mockResolvedValue()


test('should return data when fetchData request success', () => {
   const fetchData = jest.fn();
    fetchData.mockResolvedValue({name: 'sam'})
   return fetchData().then(res => {
       expect(res).toEqual({name: 'sam'})
   })
})

3.改變函數實現。 有時不想使用默認的mock函數jest.fn(),尤其是測試回調函數的時候,你想提供回調函數實現,比如上面的forEach, 確實寫一個真實的回調函數進行測試,心里更有底一點。mock 函數實現也有兩種方法,jest.fn() 可以接受一個參數,這個參數就可以是一個函數實現。forEach 中的mock 函數就可以成mock 函數提供了一個方法mockImplementation(), 它的參數也是一個函數實現,使用mockImplementation() 來mock fetchData,讓它返回{name: 'sam'}

 

 注:VSCode的終端窗口中輸入yarn test 就可以進行測試了

  • 配置jest :npx jest --init
  • 生成代碼覆蓋率:npx jest --coverage
  • Jest識別三種測試文件:
    • 測試文件后綴為js,jsx,ts,tsx
    • 測試文件需要放在tests/unit/目錄下或者是/__tests__/目錄下
    • 以xx.test.js/...結尾的文件,以xx.spec.js/...結尾的文件,
      只要滿足這三個要求的測試文件,使用運行jest時就會自動執行


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM