需要测试的代码:
functiononce(fn){varreturnValue,called=false;returnfunction(){if(!called){called=true;returnValue=fn.apply(this,arguments);}returnreturnValue;};}
间谍(spy)
用spy测试上面的函数:
it("calls the original function",function(){varcallback=sinon.spy();varproxy=once(callback);proxy();assert(callback.called);});
sinon.spy进行绑定。
once(callback) 绑定回调函数。
assert(callback.called) 断言。
下面这段代码判定函数被调用了一次:
it("calls the original function only once",function(){varcallback=sinon.spy();varproxy=once(callback);proxy();proxy();assert(callback.calledOnce);// ...or:// assert.equals(callback.callCount, 1);});
也可以对实体和参数进行断言:
it("calls original function with right this and args",function(){varcallback=sinon.spy();varproxy=once(callback);varobj={};proxy.call(obj,1,2,3);assert(callback.calledOn(obj));assert(callback.calledWith(1,2,3));});
Stubs(桩??)
it("returns the return value from the original function",function(){varcallback=sinon.stub().returns(42);varproxy=once(callback);assert.equals(proxy(),42);});
sinon.stub().returns(42) 对stub进行绑定。当调用stub的时候返回42。
assert.equals(proxy(), 42) 执行proxy() 并判定返回的是不是42.
测试Ajax
待测试的方法:
functiongetTodos(listId,callback){jQuery.ajax({url:"/todo/"+listId+"/items",success:function(data){// Node-style CPS: callback(err, data)callback(null,data);}});}
当执行getTodos方法的时候跳转到url指定的地址并且返回callback函数。
为了判定是否正确绑定url我们对jQuery.ajax打个桩。
after(function(){// When the test either fails or passes, restore the original// jQuery ajax function (Sinon.JS also provides tools to help// test frameworks automate clean-up like this)jQuery.ajax.restore();});it("makes a GET request for todo items",function(){sinon.stub(jQuery,"ajax");getTodos(42,sinon.spy());assert(jQuery.ajax.calledWithMatch({url:"/todo/42/items"}));});
after 方法是为了当测试方法执行完之后jquery.ajax()方法复原,不会对原来的代码产生影响。
这里存在一个疑问:如果原方法中没有callback参数,如何进行spy???
虚拟 XMLHTTP请求
模拟 xmlhttp请求:
varxhr,requests;before(function(){xhr=sinon.useFakeXMLHttpRequest();requests=[];xhr.onCreate=function(req){requests.push(req);};});after(function(){// Like before we must clean up when tampering with globals.xhr.restore();});it("makes a GET request for todo items",function(){getTodos(42,sinon.spy());assert.equals(requests.length,1);assert.match(requests[0].url,"/todo/42/items");});
before方法在正式测试之前进行一系列的准备工作:模拟http请求,并发送请求。
it中执行方法并断言。请注意这个地方,前面用的是stub方法,绑定后执行ajax。而在这里是在before里面调用了ajax(一开始我没看出来)。
分析:在运行之前开始ajax的调用,当运行到gettodos方法的时候调用ajax执行gettodos里面的jquery.ajax方法,如果没有xhr.onCreate的话就不会有ajax请求也就不会调用ajax方法了。然后通过sinon.spy()进行断言。
after方法恢复原来所有的更改。
模拟 服务
(相对于前面的模拟request请求)
此部分模拟了后台的服务,不用跳转到后台进行执行了:
varserver;before(function(){server=sinon.fakeServer.create();});after(function(){server.restore();});it("calls callback with deserialized data",function(){varcallback=sinon.spy();getTodos(42,callback);// This is part of the FakeXMLHttpRequest APIserver.requests[0].respond(200,{"Content-Type":"application/json"},JSON.stringify([{id:1,text:"Provide examples",done:true}]));assert(callback.calledOnce);});
执行测试之前模拟服务端,相当于服务端开启
sinon.spy()监听。
执行getTodos()方法。用模拟的server服务返回需要的参数。然后断言方法是否执行一次
执行完恢复为原来的状态。
那什么模拟时间的是什么乱七八糟的东西,你们自己看吧,用到的应该比较少。OK,搞定收工~
自己乱写的,不喜勿喷~