【前端单元测试入门03】Sinon
前端测试存在的问题
在讲Sinon之前,我们得先讲一下在学习了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的另一种玩法,即对原有函数的监控玩法,在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
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);
});
测试结果如下:

根据测试结果可以了解到,原函数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();
运行上述测试用例得到以下结果:

小结
Sinon主要是一个测试辅助工具,通过伪装和拦截,来模拟与其他系统或函数的操作,可以解耦测试的依赖。
在上面只讲到了Sinon的spy、stub和mock三个函数,其实还有fake XHR(模拟xhr请求)、fack server(模拟服务器)以及fake timer(模拟定时器)等操作。这里就不多讲了,具体的可以查看此API:Sinon v4.1.6。
【前端单元测试入门03】Sinon的更多相关文章
- 【前端单元测试入门02】react的单元测试之Enzyme
React项目的单元测试 React的组件结构和JSX语法,对上一章的内容来讲进行测试显得很勉强. React官方已经提供了一个测试工具库:react-dom/test-utils 只是用起来不够方便 ...
- 【前端单元测试入门05】react的单元测试之jest
jest jest是facebook推出的一款测试框架,集成了前面所讲的Mocha和chai,jsdom,sinon等功能. 安装 npm install --save-dev jest npm in ...
- 【前端单元测试入门01】Mocha与chai
Mocha 的简介 Mocha是流行的JavaScript测试框架之一,通过它添加和运行测试,从而保证代码质量 Mocha 的安装与配置 全局安装Mocha npm install -g mocha ...
- 【前端单元测试入门04】Karma
Karma 官方介绍 A simple tool that allows you to execute JavaScript code in multiple real browsers. 即一个允许 ...
- Jest 前端单元测试工具
Jest和enzyme 前端单元测试工具 什么是Jest? Jest是一个令人愉悦的JavaScript测试框架,其重点是简单性. 它适用于使用以下项目的项目:Babel,TypeScript,Nod ...
- openresty 前端开发入门五之Mysql篇
openresty 前端开发入门五之Mysql篇 这章主要演示怎么通过lua连接mysql,并根据用户输入的name从mysql获取数据,并返回给用户 操作mysql主要用到了lua-resty-my ...
- 每天成长一点---WEB前端学习入门笔记
WEB前端学习入门笔记 从今天开始,本人就要学习WEB前端了. 经过老师的建议,说到他每天都会记录下来新的知识点,每天都是在围绕着这些问题来度过,很有必要每天抽出半个小时来写一个知识总结,及时对一天工 ...
- Android Studio单元测试入门
Android Studio单元测试入门 通常在开发Android app的时候经常会写一些小函数并验证它是否运行正确,通常做法我们是把这个函数放到某个界面(Activity上)执行一下,运行整个工程 ...
- 使用 gulp 搭建前端环境入门篇(转载)
本文转载自: 使用 gulp 搭建前端环境入门篇
随机推荐
- iOS视频直播
视频直播技术点 视频直播,可以分为 采集,前处理,编码,传输, 服务器处理,解码,渲染 采集: iOS系统因为软硬件种类不多, 硬件适配性比较好, 所以比较简单. 而Android端市面上机型众多, ...
- Java8的一些新特性
速度更快: 代码更少(增加了新的语法Lamdba表达式): Lamdba操作符"->" 语法格式: 左侧:参数列表 右侧:接口抽象方法的实现功能 Lamdba表达式 3.强大 ...
- redis 突然大量逐出导致读写请求block
现象 redis作为缓存场景使用,内存耗尽时,突然出现大量的逐出,在这个逐出的过程中阻塞正常的读写请求,导致 redis 短时间不可用: 背景 redis 中的LRU是如何实现的? 当mem_used ...
- 利用 xrandr 命令修改屏幕分辨率
问题背景 电脑外接着一个 23' 的显示器,分辨率为 1920*1080. 操作系统:ubuntu 14.04 今天,通过 Setting->Displays 中选择外接屏的分辨率时,发现最大只 ...
- win7 vs2012+wdk8.0 搭建wdf驱动开发环境
开发环境搭建:系统:win7 x64工具:vs2012 + WDK8.0插件:wdfcoinstaller.msi(1)先安装vs2012,再安装wdk8.0,这样在打开vs2012时可以创建wind ...
- mysql常用基础操作语法(十一)~~字符串函数【命令行模式】
注:sql的移植性比较强,函数的移植性不强,一般为数据库软件特有,例如mysql有mysql的函数,oracle有oracle的函数. 1.concat连接字符串: 从上图中可以看出,直接使用sele ...
- 新工具︱微软Microsoft Visual Studio的R语言模块下载试用Ing...(尝鲜)
笔者:前几天看到了以下的图片,着实一惊.作为R语言入门小菜鸟,还是觉得很好看,于是花了一点时间下载下来试用了一下,觉得还是挺高大上的. 就是英文不好是硬伤.下面贴给小白,我当时的下载步骤与遇见的问题. ...
- 如何访问pcie整个4k的配置空间
目前用于访问PCIe配置空间寄存器的方法需要追溯到原始的PCI规范.为了发起PCI总线配置周期,Intel实现的PCI规范使用IO空间的CF8h和CFCh来分别作为索引和数据寄存器,这种方法可以访问所 ...
- Linux显示已经挂载的分区列表
Linux显示已经挂载的分区列表 youhaidong@youhaidong-ThinkPad-Edge-E545:~$ df -h 文件系统 容量 已用 可用 已用% 挂载点 /dev/sda8 1 ...
- VMware vSphere学习整理
知识点整理 内存选择 一般来说,每个虚拟机需要的内存在1~4GB甚至更多,还要为VMware ESXi预留一部分内存 2个6核的2U服务器配置64GB内存,4个6核或8核心的4U服务器配置128GB或 ...