1 前言
- 本文更多的使用JavaScript VUE的单元测试作为示例。
- 如果使用Google Chrome浏览器预览页面,推荐配合vue-devtools,可对VUE页面元素属性查看和修改。
2 Jasmine
jasmine-core@2.8.0__点击查看官方文档,如果用的是jasmine-1.x的,关于2.0升级说明
- Jasmine不依赖于任何框架,所以适用于所有的Javascript代码。
- 使用一个全局函数 describe 来描述每个测试,并且可以嵌套。
- describe函数有2个参数,一个是字符串用于描述,一个是函数用于测试。
- 在该函数中可以使用全局函数 it 来定义Specs,也就是单元测试的主要内容, 使用 expect 函数来测试:
|
|
如果想去掉某个describe/it,无须注释掉整段代码,只需要在需要忽略的describe/it前面加上x即可忽略该describe/it,即使用xdescribe/xit。
3 Jasmine基本示例
3.1 AOP before & after
- beforeAll(): 模块第一个spec之前执行,只执行一次
- afterAll(): 模块最后一个spec之后执行,只执行一次
- beforeEach(): 每个spec之前执行
- afterEach(): 每个spec之后执行
AOP,即面向方面的编程(Aspect Oriented Programming)。比如有时候为了测试一个对象,可能需要多次创建和销毁它,所以为了避免冗余代码,使用它们是最佳选择。
3.2 常用Matcher
- toBe(): 一个基本的 matcher 用来定义判断规则.
|
|
- toEqual(): 注意和toBe()的区别: 一个新建的Object不是(not to be)另一个新建的Object,但是它们是相等(to equal)的。
|
|
- toMatch(): 可以使用字符串或者正则表达式来验证,以及其他一些特殊验证,比如undefined或者boolean的判断
|
|
- toThrow(): 可以检查函数所抛出的异常。
- 自定义Matcher: 使用beforeEach方法在每个测试执行前添加一个matcher
|
|
- jasmine.any(): 代表一类数据传入matcher中.
|
|
3.3 Spy使用
3.3.1 基本使用
- Spy用来追踪函数的调用历史信息(是否被调用、调用参数列表、被请求次数等)。
- Spy仅存在于定义它的describe和it方法块中,并且每次在spec执行完之后被销毁。
- 当在一个对象上使用spyOn方法后即可模拟调用对象上的函数,此时对所有函数的调用是不会执行实际代码的。
|
|
3.3.2 Spy.calls
- calls.any(): 被Spy的函数一旦被调用过,则返回true,否则为false;
- calls.count(): 返回被Spy的函数的被调用次数;
- calls.argsFor(index): 返回被Spy的函数的调用参数,以index来指定参数;
- calls.allArgs():返回被Spy的函数的所有调用参数;
- calls.all(): 返回calls的上下文,这将返回当前calls的整个实例数据;
- calls.mostRecent(): 返回calls中追踪的最近一次的请求数据;
- calls.first(): 返回calls中追踪的第一次请求的数据;
- object: 当调用all(),mostRecent(),first()方法时,返回对象的object属性返回的是当前上下文对象;
- calls.reset(): 重置Spy的所有追踪数据;
3.3.3 Spy.and
注意: 这些调用将不会对变量产生作用,所以 a 仍为null。如果需要调用产生实际的作用:
- and.CallThrough(): 需要执行实际的代码。
- and.returnValue(): 强制指定函数的返回值。
- and.CallFake(): 传入一个function作为参数去代替原本的function。
|
|
Spy中的and还有一些function的作用如下:
- and.throwError():模拟异常的抛出。
- and.stub():恢复到原始的spyOn()方法
3.3.4 Spy其他创建方式
甚至在没有function的时候可以使用Jasmine的 createSpy 和 createSpyObj 创建一个spy:
|
|
其效果相当于spyOn使用在了已存在的function上。
3.4 时间控制
概念:上面的方法都在程序顺序执行的前提下执行,但
Clock提供的function:
- 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849- ```tick()```:接收参数:毫秒值。推进时间。- ```mockDate()```:接收参数:Date。指定时间,默认当前。- ```install()```:创建mocked Clock- ```uninstall()```:关闭mocked Clock#### 3.5 异步Javascript最大的特色之一就是异步,之前介绍的方法如果存在异步调用,大部分测试时可能会不通过。因此,需要等异步回调之后再进行测试。##### 3.5.1 通过默认 done()- Jasmine-1.x的 ```runs()``` 、```waits()```、```waitsFor()``` 已经被移除。- 2.x起提供了类似Mocha/chai的done,支持调用```beforeEach()``` , ```it()``` , 和```afterEach()``` 的时候,可以带一个可选的参数done ,当有参数时spec执行完成之后必须调用```done()```来告诉Jasmine异步操作已经完成。- 默认Jasmine的超时时间是5s,可以通过全局的```jasmine.DEFAULT_TIMEOUT_INTERVAL``` 设置。```jsdescribe("Jasmine 异步测试演示", function () {var value;beforeEach(function (done) { // 传入了donesetTimeout(function () {value = 0;done(); // 必须在结束是调用,否则将超时错误}, 1);});it("支持异步执行", function (done) {value++;expect(value).toBeGreaterThan(0);done(); // 外层的it,例如这里,如果没有调用,会影响‘5秒钟‘中的it超时});describe("5秒钟", function () {var originalTimeout;beforeEach(function () {originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL; // 这里只是做了保存默认值操作jasmine.DEFAULT_TIMEOUT_INTERVAL = 6000;});it("takes a long time", function (done) {setTimeout(function () {done();}, 5000);});afterEach(function () {jasmine.DEFAULT_TIMEOUT_INTERVAL = originalTimeout;});});});
3.5.1 通过jasmine-ajax插件
jasmine-ajax插件用来模拟测试ajax。注意这是个单独的文件,需要额外引用。
这是官方文档_示例,插件示例是 XMLHttpRequest 配合 spy 使用的示例。
原理同样是通过 mock 返回的数据。
4 VUE示例
4.1 生成vue实例
|
|
4.2 filter测试
vue代码
|
|
测试代码
|
|
4.3 异步更新DOM测试
- 使用Vue.nextTick来查看异步数据更新后dom是否变化.
- 依赖 DOM 更新结果的断言必须在 Vue.nextTick 回调中进行.
测试代码
|
|
4.4 组件有用户交互(模拟点击/输入)
vue代码
|
|
测试代码
|
|
4.5 拦截其他依赖(Mock)
有时候我们还会遇到需要拦截mock,拦截vuex的情况。这时候就需要引入:inject-loader,可以对组件内部的任何模块依赖进行内容替换,不仅是 api 模块还可以是子 component。
vue代码
|
|
测试代码
|
|
4.6 其他依赖注入
如 Mock的Component、store、router等。
|
|
5 AngularJS示例
以下代码出自Github_jsprodotcom/source
说明:源代码中scenario.js文件即为详解一中的e2e测试代码,运行 test/e2e/runner.html 来查看结果。
5.1 测试Controller和Factory
App代码示例
|
|
测试代码一:测试TodoController
|
|
测试代码二:测试notesFactory
|
|
5.2 测试Filter
App代码示例
|
|
测试代码
|
|
5.3 测试Directive
App代码示例
|
|
测试代码
|
|
5 参考文章
关于前端开发谈谈单元测试
为什么要单元测试?
Jasmine入门(结合示例讲解)
Javascript测试框架Jasmine(六):异步代码测试
VUE官网_单元测试
Vue 的单元测试探索(一)
Vue单元测试case写法
五个值得尝试的前端开发工具
Angular (二) Jasmine单元测试和端到端测试
unit-and-e2e-testing-in-angularjs