目录

  • 简介
  • 编写测试
  • Spy
  • Mock
  • Stub
  • Test a Promise
  • xhr
  • Hooks
  • Coverage

简介

  • Mocha是流行的JavaScript测试框架之一,通过它添加和运行测试,从而保证代码质量

    • 既可以测试简单的JavaScript函数,又可以测试异步代码,因为异步是JavaScript的特性之一
    • 可以自动运行所有测试,也可以只运行特定的测试;
    • 可以支持before、after、beforeEach和afterEach来编写初始化代码。
    • describe块称为"测试套件"(test suite),表示一组相关的测试,可以有多个
  • chai 断言库(node里也有自带的assert)
  • sinon 可以单独测试spies, stubs and mocks,适用于任何的测试框架

编写测试

npm init --y
npm i mocha chai -S
// src/myClass.js
class MyClass{constructor(){console.log('initiate')}add(arg1, arg2){const res = arg1+arg2return res}
}module.exports = MyClass// myClass.spec.js
const MyClass = require('../src/myClass')
const myObj = new MyClass()
const chai = require('chai')
const expect = chai.expectdescribe('Test suit', ()=>{it('Test the add method',()=>{expect(myObj.add(1, 2)).to.be.equal(3)})
})// package.json
"scripts": {"test": "mocha './specs/**/*.spec.js'"  // mocha './specs/*.@(js|jsx)'
}

chai是什么?

// 测试失败用抛异常来处理,有点繁琐,所以就有了断言库的出现(chai断言库)
describe('Test suit', ()=>{it('Test the add method',()=>{if(myObj.add(1, 2)!==3){throw new Error('错误~~~'’);}})
})

Spy

它可以追踪
谁进入你家?
它进入多少次?
它携带了什么?
它什么时候离开?
它离开的时候做了什么?

npm i sinon -D// src/myClass.js
class MyClass{constructor(){console.log('initiate')}add(arg1, arg2){const res = arg1 + arg2return res}callAnotherFn(arg1, arg2){return this.add(arg1, arg2)}callTheCallback(callback){callback()}
}module.exports = MyClass// myClass.spec.js
// ...
const sinon = require('sinon')describe('Test suit', ()=>{// ...it('spy the add method',()=>{const spy = sinon.spy(myObj, 'add') // 追踪add函数是否被调用myObj.callAnotherFn(1, 2)// 断言add函数在里面是否被执行一次// sinon.assert.calledOnce(spy)expect(spy.calledTwice).to.be.falseexpect(spy.calledWith(1, 2)).to.be.true})it('spy the callback method',()=>{const spy = sinon.spy() // 设置一个追踪器myObj.callTheCallback(spy)expect(spy.calledOnce).to.be.true})
})

Mock

受到前面测试函数的影响,会被执行两次,
所以要创建mock,不会改变实际的对象,只是创建一个包装器

// src/myClass.js
class MyClass{constructor(){console.log('initiate')}add(arg1, arg2){const res = arg1 + arg2console.log(res)return res}sayHello(str){console.log(str)}callAnotherFn(arg1, arg2){this.sayHello()return this.add(arg1, arg2)}callTheCallback(callback){callback()}
}module.exports = MyClass// myClass.spec.js
describe('Test suit', ()=>{//...// it('mock the sayHello method',()=>{//     myObj.callAnotherFn(3, 4)// })it('mock the sayHello method',()=>{const mock = sinon.mock(myObj)const expetcation = mock.expects('sayHello')expetcation.exactly(1)expectation.withArgs('hello world 111')myObj.callAnotherFn(3, 4)mock.verify() // 验证对模拟的所有期望})
})

Stub

// myClass.spec.js
describe('Test suit for stub', ()=>{it('stub the add method', ()=>{let stub = sinon.stub(myObj, 'add') // 用来替换myObj.add函数,自定义返回结果(模拟add函数)stub.withArgs(10, 20).onFirstCall().returns(100) // 定义第一次执行时的返回结果为100.onSecondCall().returns(200) // 定义第二次执行时的返回结果为200expect(myObj.callAnotherFn(10, 20)).to.be.equal(100) // 测试返回结果expect(myObj.callAnotherFn(10, 20)).to.be.equal(200)})
})

Test a Promise

npm i chai-as-promised// src/myClass.js
class MyClass{// ...testPromise(){return new Promise((resolve, reject)=>{setTimeout(() => resolve(3), 4000)}).then(result => {return result*2})}}// myClass.spec.js
const chaiaspromise = require("chai-as-promised")
chai.use(chaiaspromise)describe.skip("Test the promise", function() {it("Promise test case", function(done) {this.timeout(4000)myObj.testPromise().then(function(result) {expect(result).to.be.equal(6)done()})})
})describe("Test the promise", function() {it("Promise test case with chai-as-promised", function() {this.timeout(0)return expect(myObj.testPromise()).to.eventually.equal(6)})
})

xhr

npm i nock -D
npm i xmlhttprequest -S//

Hooks

// myClass.spec.js
describe('Test suit', ()=>{after(function() {console.log("===================== After the test suit")})before(function() {console.log("===================== Before the test suit")})afterEach(function() {console.log("======= After every test case inside this test suit")})beforeEach(function() {// Sinon包装必须在测试用例之前或之后恢复sinon.restore()console.log("======= Before every test case inside this test suit")})it('Test the add method',()=>{expect(myObj.add(1, 2)).to.be.equal(3)})it('spy the add method',()=>{const spy = sinon.spy(myObj, 'add') // 追踪add函数是否被调用myObj.callAnotherFn(1, 2)// 断言add函数在里面是否被执行一次// sinon.assert.calledOnce(spy)expect(spy.calledTwice).to.be.falseexpect(spy.calledWith(1, 2)).to.be.true})})/* 输出
===================== B
efore the test suit
======= Before every test case inside this test suit
3✔ Test the add method
======= After every test case inside this test suit
======= Before every test case inside this test suit
3✔ spy the add method
======= After every test case inside this test suit
===================== After the test suit
*/

Coverage

npm i nyc -D// package.json
"scripts": {"coverage": "nyc --reporter=text npm run test""coverage": "nyc --reporter=lcov --reporter=text npm run test"  // lcov 生成报告
},
/* "nyc":{"include": "src", // 测试覆盖率只测试src文件夹"exculed": "specs"
},
*/// 或者建立外部文件
// .nycrc.json
{"include": "src","exclude": "specs","check-coverage": true,"branches": 80,"lines": 80,"functions": 80,"statements": 80,"report-dir": "./reports","skip-full": true
}

github参考代码

参考:
mocha官网
详细的mocha
sinon官网

【前端测试与集成】使用mocha和sinon进行单元测试相关推荐

  1. 前端测试简述及使用Karma/Mocha实现的集成测试栗子(Travis CI/Coverage)

    前端测试 开发类型 TDD (Test Driven Development),测试驱动开发 BDD (Behavior Driven Development),行为驱动开发 // add.js fu ...

  2. 如何使用 mocha 和 sinon 集成单元测试--单元测试示例及分析(上)

    使用 mocha 集成单元测试(上) 项目地址:https://github.com/Jay-tian/j... 安装依赖 yarn add jquery mocha mochawesome ista ...

  3. 前端新手使用karma+mocha+chai+sinon 进行angularjs 单元测试

    这里只谈如何搭建环境. 选型:在jasmine 和 mocha+chai中间比较了一下,根据项目需要选择了后者. 安装依赖包和环境 直接执行下列命令安装或在项目目录下 运行npm install(pa ...

  4. 这一次,彻底入门前端测试,覆盖单元测试、组件测试(2.4w 字)

    前端测试一直是前端工程化中很重要的话题,但是很多人往往对测试产生误解,认为测试不仅没有什么用而且还浪费时间,或者测试应该让测试人员来做,自己应该专注于开发.所以,文章开头会先从"软件工程语境 ...

  5. 执行前端测试的必要性

    对于网站的真实前端测试,必须在不同的设备和浏览器(具有多个版本)上检查功能和性能.在不同浏览器.浏览器版本和操作系统上评估网站的过程称为跨浏览器测试,它被认为是每个前端网站测试计划的重要组成部分,用于 ...

  6. 【node测试系列】几款前端测试断言库(Assertions lib)的选型总结

    参考文章 http://blog.lvscar.info/post/... 在编写前端测试代码的过程中, 几乎所有的测试框架都提供了根据功能.模块(module ,spec )来切分测试用例的设计, ...

  7. 前端测试框架—jest基本使用

    前端测试框架-jest基本使用 前言 jest 常见匹配器 基本类型 boolean Number String Array,Set 异常 取反 命令行工具使用 异步代码测试方法 钩子函数 分组(钩子 ...

  8. 为什么必须执行前端测试?

    对于网站的真实前端测试,必须在不同的设备和浏览器(具有多个版本)上检查功能和性能.在不同浏览器.浏览器版本和操作系统上评估网站的过程称为跨浏览器测试,它被认为是每个前端网站测试计划的重要组成部分,用于 ...

  9. 前端测试 —— 技术选型及入门

    目录 为什么要撰写前端的测试? 前端测试的类型 技术选型 结构介绍 为什么要撰写前端的测试? 在前端发展日益壮大后,我们在项目中往往引入了工程化.模块化的概念,这和数年前前端极度依赖后端渲染以及切图工 ...

最新文章

  1. 《从问题到程序:用Python学编程和计算》——3.4 定义函数
  2. 移动端总结和手机兼容问题
  3. 一种基于超体素结合粒子群与模糊聚类实现点云分割的优化算法
  4. leftjoin多个on条件_MYSQL|为什么LEFT JOIN会这么慢?
  5. android 复制u盘文件到手机本地_如何导出Android中的文件(把Android当做U盘)
  6. 机器学习如何计算特征的重要性_机器学习之特征工程
  7. 微软IIS6漏洞:服务器敏感信息易被窃
  8. Python用20行代码实现一个验证码的输入与验证(完整源码)
  9. Oracle 11g xe版本---总结1
  10. 苹果的“价格战”还能走多远? | 畅言
  11. Windows Server 2008 优化
  12. inline-block和float
  13. Servlet请求转发RequestDispatcher接口
  14. JS实现页面字体繁简转换
  15. 《Python程序设计实验指导书》81个实验项目选做参考
  16. thinkpad指点杆(trackpoint)在WPS的word文档中失效的解决办法
  17. MySQL的系统信息函数和加密解密函数(十四)
  18. 庆科EMW3080 mxos开发环境搭建helloworld编译
  19. Hadoop数据迁移工具DistCp
  20. one coin,oneworld

热门文章

  1. 不安装DBC2000安装架设传奇服务端的方法
  2. p2p断开的两种情况:WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY(4)和WLAN_REASON_DEAUTH_LEAVING(3)
  3. RN 封装 Android原生组件
  4. 云计算机的一大特征是什么,云计算最大的特征是什么?
  5. spark常见面试题
  6. Linux内核由32位升到64,将Ubuntu从32位版本升级到64位版本
  7. 二、Prometheus TLS加密认证和基于 basic_auth 用户名密码访问
  8. 微星超龙显卡的性能模式无法开机的原因与解决办法
  9. Java锁Synchronized对象锁和类锁区别(搬运)
  10. 运筹学作业——社会网络中的信息传播优化问题