在講Sinon以前,咱們得先講一下在學習了Mocha、chai以及enzyme以後,咱們的前端測試還存在的一些問題。
好比前臺測試須要與後臺交互,獲取後臺數據後再根據相應數據進行測試。
又好比一個函數測試依賴另外一個函數,咱們能夠根據測試的目的去模擬另外一個函數,講二者的測試分開,從而達到測試中也能解耦的目的。前端
Sinon是用來輔助咱們進行前端測試的,在咱們的代碼須要與其餘系統或者函數對接時,它能夠模擬這些場景,從而使咱們測試的時候再也不依賴這些場景。
Sinon有主要有三個方法輔助咱們進行測試:spy,stub,mock。npm
在講解用法前,先看一下咱們的測試項目結構:
編程
而後這裏的測試例子用的是官網上的例子,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的內容爲空。
那麼接着安裝Sinonapp
npm install --save-dev sinon
官方對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值,表示函數是否被調用。
測試結果爲:
this
如今來看看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
來看看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); });
測試結果以下:
根據測試結果能夠了解到,原函數func的內容確實沒有被執行,由於沒有打印1。
更多API查看Sinon之stub
看一下官網的介紹
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();
運行上述測試用例獲得如下結果:
Sinon主要是一個測試輔助工具,經過假裝和攔截,來模擬與其餘系統或函數的操做,能夠解耦測試的依賴。
在上面只講到了Sinon的spy、stub和mock三個函數,其實還有fake XHR(模擬xhr請求)、fack server(模擬服務器)以及fake timer(模擬定時器)等操做。這裏就很少講了,具體的能夠查看此API:Sinon v4.1.6。