原文链接http://sinonjs.org/
下载地址:http://sinonjs.org/releases/sinon-1.5.0.js
开始
需要测试的代码:
function once(fn) {
var returnValue, called = false;
return function () {
if (!called) {
called = true;
returnValue = fn.apply(this, arguments);
}
return returnValue;
};
}
间谍(spy)
用spy测试上面的函数:
it("calls the original function", function () {
var callback = sinon.spy();
var proxy = once(callback);
proxy();
assert(callback.called);
});
sinon.spy进行绑定。
once(callback) 绑定回调函数。
assert(callback.called) 断言。
下面这段代码判定函数被调用了一次:
it("calls the original function only once", function () {
var callback = sinon.spy();
var proxy = once(callback);
proxy();
proxy();
assert(callback.calledOnce);
// ...or:
// assert.equals(callback.callCount, 1);
});
也可以对实体和参数进行断言:
it("calls original function with right this and args", function () {
var callback = sinon.spy();
var proxy = once(callback);
var obj = {};
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 () {
var callback = sinon.stub().returns(42);
var proxy = once(callback);
assert.equals(proxy(), 42);
});
sinon.stub().returns(42) 对stub进行绑定。当调用stub的时候返回42。
assert.equals(proxy(), 42) 执行proxy() 并判定返回的是不是42.
测试Ajax
待测试的方法:
function getTodos(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请求:
var xhr, 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请求)
此部分模拟了后台的服务,不用跳转到后台进行执行了:
var server;
before(function () { server = sinon.fakeServer.create(); });
after(function () { server.restore(); });
it("calls callback with deserialized data", function () {
var callback = sinon.spy();
getTodos(42, callback);
// This is part of the FakeXMLHttpRequest API
server.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,搞定收工~
自己乱写的,不喜勿喷~