【前端單元測試入門03】Sinon

来源:https://www.cnblogs.com/vvjiang/archive/2018/03/20/8607580.html
-Advertisement-
Play Games

前端測試存在的問題 在講Sinon之前,我們得先講一下在學習了Mocha、chai以及enzyme之後,我們的前端測試還存在的一些問題。 比如前臺測試需要與後臺交互,獲取後臺數據後再根據相應數據進行測試。 又比如一個函數測試依賴另一個函數,我們可以根據測試的目的去模擬另一個函數,講兩者的測試分開,從 ...


前端測試存在的問題

在講Sinon之前,我們得先講一下在學習了Mocha、chai以及enzyme之後,我們的前端測試還存在的一些問題。
比如前臺測試需要與後臺交互,獲取後臺數據後再根據相應數據進行測試。
又比如一個函數測試依賴另一個函數,我們可以根據測試的目的去模擬另一個函數,講兩者的測試分開,從而達到測試中也能解耦的目的。

測試輔助工具Sinon

Sinon是用來輔助我們進行前端測試的,在我們的代碼需要與其他系統或者函數對接時,它可以模擬這些場景,從而使我們測試的時候不再依賴這些場景。
Sinon有主要有三個方法輔助我們進行測試:spy,stub,mock。

Sinon的安裝

在講解用法前,先看一下我們的測試項目結構:
項目結構

然後這裡的測試例子用的是官網上的例子,once.js的內容是:

export default function once(fn) {
    var returnValue, called = false;
    return function () {
        if (!called) {
            called = true;
            returnValue = fn.apply(this, arguments);
        }
        return returnValue;
    };
}

once.test.js的內容為空。
那麼接著安裝Sinon

npm install --save-dev sinon

Sinon之spy

官方對spy的解釋:

A test spy is a function that records arguments, return value, the value of this and exception thrown (if any) for all its calls. There are two types of spies: Some are anonymous functions, while others wrap methods that already exist in the system under test.

spy生成一個間諜函數,它會記錄下函數調用的參數,返回值,this的值,以及拋出的異常。
而spy一般有兩種玩法,一種是生成一個新的匿名間諜函數,另外一種是對原有的函數進行封裝併進行監聽。

搭好上面的結構後,直接在once.test.js裡面寫入spy的使用例子:

import {assert} from 'chai'
import sinon from 'sinon'
import once from '../src/once'

describe('測試Once函數', function () {
  it('傳入Once的函數會被調用', function () {
    var callback = sinon.spy();
    var proxy = once(callback);

    proxy();

    assert(callback.called);
  });
})

如上面代碼所示,sinon.spy()會產生一個函數對象,當once調用這個函數對象後,這個函數對象通過called可以返回一個bool值,表示函數是否被調用。
測試結果為:
spy匿名函數測試結果

現在來看看spy的另一種玩法,即對原有函數的監控玩法,在once.test.js中加入以下測試用例:

it('對原有函數的spy封裝,可以監聽原有函數的調用情況', function () {
    const obj={
        func:()=>{
            return 1+1
        }
    }
    sinon.spy(obj,'func')

    obj.func(3);

    assert(obj.func.calledOnce)
    assert.equal(obj.func.getCall(0).args[0], 3);
});

測試結果:
對原有函數的監聽測試結果

更多spy的API請參考
SInon的spy

Sinon之Stub

來看看Stub的官方介紹:

Test stubs are functions (spies) with pre-programmed behavior.
They support the full test spy API in addition to methods which can be used to alter the stub’s behavior.
As spies, stubs can be either anonymous, or wrap existing functions. When wrapping an existing function with a stub, the original function is not called.

stub是帶有預編程行為的函數。
簡單點說,就是spy的加強版,不僅完全支持spy的各種操作,還能操作函數的行為。
和spy一樣,stub也能匿名,也能去封住並監聽已有函數。
然而有一點和spy不同,當封裝了一個已有函數後,原函數不會再被調用。

對於匿名的玩法我們就不說了,直接來封裝的玩法,以下是對之前spy封裝的修改:

it('對原有函數的stub封裝,可以監聽原有函數的調用情況,以及模擬返回', function () {
    const obj={
        func:()=>{
           console.info(1)
        }
    }
    sinon.stub(obj,'func').returns(42)

    const result=obj.func(3);

    assert(obj.func.calledOnce)
    assert.equal(obj.func.getCall(0).args[0], 3);
    assert.equal(result,43);
});

測試結果如下:
stub用法的測試結果

根據測試結果可以瞭解到,原函數func的內容確實沒有被執行,因為沒有列印1。
更多API查看Sinon之stub

Sinon之mock

看一下官網的介紹

Mocks (and mock expectations) are fake methods (like spies) with pre-programmed behavior (like stubs) as well as pre-programmed expectations.
A mock will fail your test if it is not used as expected.

大致意思就是mock像spy和stub一樣的偽裝方法,如果mock沒有得到期望的結果就會測試失敗。

這裡的話可能講述不是很清楚,那麼看一下代碼就很好理解了:

it('mock的測試', function () {
    var myAPI = { 
        method: function () {
            console.info("運行method")
        },
        func: function () {
            console.info("運行method")
        }
    };

    var mock = sinon.mock(myAPI);
    mock.expects("method").once().returns(2);
    mock.expects("func").twice()

    myAPI.method();
    myAPI.func();
    myAPI.func();

    mock.verify();
});

在以上代碼中,mock其實和stub很像,只不過是stub是對對象中單個函數的監聽和攔截,而mock是對多個。
mock首先會對函數進行一個預期:

   var mock = sinon.mock(myAPI);
   mock.expects("method").once().returns(2);
   mock.expects("func").twice()

比如once就是預期運行一次,如果最終驗證時函數沒有被執行或者執行多次都會拋出錯誤。
也可以操作返回結果,比如像stub一樣returns(2)依然有效。
而且與stub一樣,在mock監聽後,原有函數內容將不會執行。

在進行了預期操作後,就對函數進行實際操作:

myAPI.method();
myAPI.func();
myAPI.func();

最後再進行驗證操作:

mock.verify();

運行上述測試用例得到以下結果:
mock的測試用例結果

小結

Sinon主要是一個測試輔助工具,通過偽裝和攔截,來模擬與其他系統或函數的操作,可以解耦測試的依賴。
在上面只講到了Sinon的spy、stub和mock三個函數,其實還有fake XHR(模擬xhr請求)、fack server(模擬伺服器)以及fake timer(模擬定時器)等操作。這裡就不多講了,具體的可以查看此API:Sinon v4.1.6


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width"> <title>css畫圓</title> <style> #test { width:30 ...
  • DOM操作:創建元素、查找元素、添加新元素、替換、移除、複製、移動 ...
  • <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scal ...
  • 一、script引入(聯繫使用,小型項目) 直接下載並用 <script> 標簽引入,Vue 會被註冊為一個全局變數。 <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script> 二、Vue 提供一個官方命令 ...
  • $("body").on("click", ".submit_btn", function() { if (!$("#tel").val()) { alert("手機號不能為空"); $(this).attr("disabled", true); $(this).css({ background: ...
  • 最近閱讀《高性能JavaScript》時,在書中的“達夫設備“ 。 對此,有些感悟,同時有些疑問,希望看到的朋友,能幫忙解釋下,在此先提前感謝了。 1. 先說自己的理解吧: ”達夫設備“的目的是減少迭代次數,提高迴圈的效率,減少時間,提升性能。 感受:感覺代碼的優化,真的需要用工匠精神來雕琢,代碼的 ...
  • 本文原創 如轉載請註明出處!!! 本博客地址http://www.cnblogs.com/we-jack 本文原創,如果有同樣需求的小伙伴請第一時間聯繫我 或者在留言區留言 上次為大家提供了3D模型的展示之後 發現網上有很多想要計算3D模型錶面積和體積的需求 那麼經過掉了幾百根頭髮的艱辛歷程之後 終 ...
  • 最近使用websocket加ECharts做了一個實時監控的功能,發現了一個比較嚴重的問題,就是瀏覽器運行一段時間就會非常卡,之前在ECharts官網運行官方實例“動態數據 + 時間坐標軸”時,也遇到了同樣的情況,只是當時沒有當回事,現在來看原來是記憶體泄漏的問題。那麼是什麼原因導致的記憶體泄漏呢? 通 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...