1. 程式人生 > >【皇冠體育原始碼下載】Sinon

【皇冠體育原始碼下載】Sinon

前端測試存在的問題

在講Sinon之前皇冠體育原始碼下載dsluntan.com 企娥3393756370皇冠體育原始碼下載,我們得先講一下在學習了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);
});

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

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(模擬定時器)等操作。