您的位置:首页 > Web前端 > JavaScript

js单元测试sinonjs库

2016-04-16 02:00 591 查看
http://shaynegui.com/javascript-unit-test-sinonjs/


单元测试的意义

提高测试效率
提升代码质量
能够及时重构代码,减少依赖项
更好的理解需求和业务逻辑,因为每一个测试可能对应一个测试用例
好的测试代码可读性强,新人也能很好的通过测试代码了解到需求,减少维护成本


sinonjs就是这样一套面向js的单元测试辅助库

当我们需要测试的某个方法中,需要去某个接口发送http请求获得数据,如果你真实的发送某个请求,那么当有一天你请求的这个服务器挂掉的时候,你的单元测试就怎么也跑不过了,其实我们要测试的时候我们这个方法针对数据库的其他处理逻辑,我们并不是真的关心这个接口是否存在(甚至是否实现),那我们需要模拟一个这样的接口来返回假的数据,sinonjs就是为了解决这个问题的
{
setUp: function () {
sinon.spy(jQuery, "ajax");
},

tearDown: function () {
jQuery.ajax.restore(); // Unwraps the spy
},

"test should inspect jQuery.getJSON's usage of jQuery.ajax": function () {
jQuery.getJSON("/some/resource");

assert(jQuery.ajax.calledOnce);
assertEquals("/some/resource", jQuery.ajax.getCall(0).args[0].url);
assertEquals("json", jQuery.ajax.getCall(0).args[0].dataType);
}
}


以上代码就是模拟了ajax请求,而不会真正的发送一个xmlhttprequest出去,我们只是模拟了它返回的数据和一些行为,方便我们测试其他的逻辑


stub的用法

stub就像一个方法的存根或者树桩,我们可以预设定一些行为给它,然后进行测试
"test should stub method differently based on arguments": function () {
var callback = sinon.stub();//创建一个stub对象
callback.withArgs(42).returns(1);//当调用参数为42的时候返回1
callback.withArgs(1).throws("TypeError");//当调用参数为1的时候抛出一个异常

callback(); // No return value, no exception
callback(42); // Returns 1
callback(1); // Throws TypeError
//预先设定了这些行为,我们就可以来测试我们代码的其他逻辑
}


stub的api的一些使用场景

withArgs().returns()一般用来使用在同步的代码中
callsArgWith用来测试你需要测试的某个方法拥有一个或者多个回调,callsArgWith的第一个参数表示你要模拟第一个回调,它是个索引值,后面的参数就是你要测试回调的参数

sinon.stub(jQuery, "each").callsArgWith(1, {}).returns({});
//我们要测试$.each方法,它的参数中第0索引参数表示集合,第1个索引参数是一个回调函数,当它被调用的时候,会以callsArgWith方法的第二参数作为参数,并且返回一个空对象


yieldsTo一般用在你的测试函数的参数是一个对象,这个对象有很多属性,其中你要测试某一个属性,而刚好这个属性是一个函数

"test should fake successful ajax request": function () {
sinon.stub(jQuery, "ajax").yieldsTo("success", [1, 2, 3]);
//要模拟success函数,同时传入一个数组给success函数当作参数
jQuery.ajax({
success: function (data) {
assertEquals([1, 2, 3], data);
}
});
}


更多用法请参考sinojs的文档


mock的用法

mock更侧重与是测试代码是否作出了行为,Mock对象就像是stubs和spies的组合,并且内建了预编码地验证行为,也被成为期望。Mocks会在前期设置它们的期望(而不会像我们常见的断言一样在执行后判断是否符合期望)并且在接收到不被期望的调用时立即失败。最终mock.verify()的调用会验证所有的期望是否符合
"test should call event handler": function () {
var mock = sinon.mock();
var myElement = document.getElementsByTagName("a")[0];

dom.addEventListener(myElement, "mouseover", mock);
dom.fireEvent(myElement, "mouseover");

mock.verify();
}


如果mock被调用了超过一次,这个测试会立马失败。当verify()被调用时,如果mock没有被调用过则会抛出一个exception

也可以为一个对象上的方法创建mock,这就和spies和stubs一样。接口稍微有些不同,我们需要创建:一个mock对象和设置我们想要给于期望的方法
var mock = sinon.mock(jQuery);
mock.expects("each").once().callsArgWith(1, {}).returns({});
//代码创建了jQuery.each方法的期望:只被调用一次,并且指示它向之前的stub一样运作


mock的期望

Sinon的mocks支持了spy和stub的接口,尽管spy的接口比起mocks的接口来说没那么有趣。通常前期你会使用如下的方法来设置期望。注意这些方法也会返回expectation,这样你可以使用链式调用,符合声明使得代码可读性更高

execptation.atLeast(callCount) 确保mock的被调用次数达到指定的次数
expectation.atMost(callCount)确保mock的被调用次数不会超过指定的次数
expectation.exactly(callCount)指定mock被调用的次数。
expectation.never()exactly(0)的快捷方法。
expectation.once()exactly(1)的快捷方法。
expectation.twice()exactly(2)的快捷方法。
expectation.thrice()exactly(3)的快捷方法。
expectation.withArgs(arg1, arg2, ...)就像spy的calledWith(arg1, arg2, ...)方法一样,只不过是它是用作前期对期望的设置。
expectation.withExactArgs(arg1, arg2, ...)就像spy的calledWithExactly(arg1, arg2, ...)方法一样,只不过是它是用作前期对期望的设置。
expectation.on(thisObj)期望this值匹配指定的对象

restore方法可以用来还原stub和mock的默认行为,即让测试方法变成原来该做的事情
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: