博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Jasmine中文指南
阅读量:6786 次
发布时间:2019-06-26

本文共 14930 字,大约阅读时间需要 49 分钟。

jasmine是一款非常流行的测试框架,不依赖任何别的库,语法简单,本文是2.1版本的api中文指南.

运行条件

  • npm install -g jasmine

  • jasmine JASMINE_CONFIG_PATH=jasmine.json

  • jasmine.json配置文件可以随意命名,内容格式如下

{
"spec_dir": "jasminetest", "spec_files": [ "*.js" ] }
  • spec_dir代表要测试用例的目录,spec_files代表要测试的文件信息

一个简单的jasmine测试用例总是以describe开始的,它代表一组相似的测试用例,然后具体的测试用例以it开始,先看看下面简单的例子

describe(' test some code ', function(){
var foo = 'foo'; it(' expect foo equal foo ', function(){
expect(foo).toEqual('foo'); });})

下面是jasmine的常用断言方法,在任何断言方法前面加上not,代表相反的意思.

toBe

类似于`===`
expect(true).toBe(true);

toEqual

比较变量字面量的值
expect({
foo: 'foo'}).toEqual( {
foo: 'foo'} );

toMatch

匹配值与正则表达式
expect('foo').toMatch(/foo/);

toBeDefined

检验变量是否定义
var foo = {
bar: 'foo'};expect(foo.bar).toBeDefined();

toBeNull

检验变量是否为`null`
var foo = null;expect(foo).toBeNull();

toBeTruthy

检查变量值是否能转换成布尔型`真`值
expect({}).toBeTruthy();

toBeFalsy

检查变量值是否能转换成布尔型`假`值
expect('').toBeFalsy();

toContain

检查在数组中是否包含某个元素
expect([1,2,4]).toContain(1);

toBeLessThan

检查变量是否小于某个数字
expect(2).toBeLessThan(10);

toBeGreaterThan

检查变量是否大于某个数字或者变量
expect(2).toBeGreaterThan(1);

toBeCloseTo

比较两个数在保留几位小数位之后,是否相等,用于数字的精确比较
expect(3.1).toBeCloseTo(3, 0);

toThrow

检查一个函数是否会throw异常
expect(function(){
return a + 1;}).toThrow(); // trueexpect(function(){
return a + 1;}).not.toThrow(); // false

toHaveBeenCalled

检查一个监听函数是否被调用过
  • 代码见下面的监听函数部分

toHaveBeenCalledWith

检查监听函数调用时的参数匹配信息
  • 代码见下面的监听函数部分

测试前后注入

  • beforeEach

    在describe里的每个it执行前调用

describe('test code inject', function(){
var foo; // 每次给foo加1 beforeEach(function(){
foo += 1; }); it('expect foo toBe 1 ', function(){
expect(foo).toBe(1); }); it('expect foo toEqual 2 ', function(){
expect(foo).toEqual(2); });});
  • afterEach

    在describe里的每个it执行后调用

describe('test code inject', function(){
var foo; // 每次给foo加1 beforeEach(function(){
foo += 1; }); // 重置变量foo afterEach(function(){
foo = 0; }); it('expect foo toBe 1 ', function(){
expect(foo).toBe(1); }); it('expect foo toEqual 1 ', function(){
expect(foo).toEqual(1); });});
  • beforeAll

    保证在describe里所有的it执行之前调用

describe('test beforeAll ', function(){
var foo; // 只执行一次,保证在it执行之前执行 beforeAll(function(){
foo += 1; }); it('expect foo toBe 1 ', function(){
expect(foo).toBe(1); }); it('expect foo toEqual 1 ', function(){
expect(foo).toEqual(1); });});
  • afterAll

    保证在describe里所有的it执行完成之后调用

describe('test beforeAll ', function(){
var foo; // 只执行一次,保证在it执行之前执行 beforeAll(function(){
foo += 1; }); afterAll(function(){
foo = 0; }); it('expect foo toBe 1 ', function(){
expect(foo).toBe(1); foo += 1; }); it('expect foo toEqual 2 ', function(){
expect(foo).toEqual(2); }); // foo 0});

this关键字

  • describe里的每个beforeEach,it,afterEachthis都是相同的.
describe('test this context', function(){
beforeEach(function(){
this.bar = 'yicai'; }); afterEach(function(){
console.log(this.bar); // yicai }); it('expect this.bar yicai ', function(){
console.log(this.bar); // yicai }); it('expect this.bar yicai ', function(){
console.log(this.bar); // yicai });});

嵌套describe

  • 不同层次的it执行时,会按从外到内依次执行beforeEach,每个it执行结束时,会按从内到外依次执行afterEach.
describe('test nesting describe ', function(){
var foo = 0; beforeEach(function(){
foo += 1; }); afterEach(function(){
foo = 0; console.log('second invoke parent afterEach'); }) it('expect foo toBe 1', function(){
expect(foo).toBe(1); }); describe('child describe ', function(){
beforeEach(function(){
foo += 1; }) afterEach(function(){
console.log('first invoke child afterEach'); }) it('expect foo toEqual 2', function(){
expect(foo).toEqual(2); }); })});

禁用describe与it

  • 当在describeit前面加上x前缀时,可以禁掉当前describe和it测试

  • 当使用xit或者it里不包含函数体时,测试结果会显示挂起spec字样

spy监视函数执行

  • spyOn方法可以添加对某个对象下的函数执行情况的监控
describe('test spy ', function(){
var spyobj, bar = null; beforeEach(function(){
spyobj = {
setBar: function(val){
bar = val; } } spyOn(spyobj, 'setBar'); spyobj.setBar('123'); spyobj.setBar('1', '2'); }); it('check spyobj invoke track', function(){
// 检查是否监听函数是否调用过 expect(spyobj.setBar).toHaveBeenCalled(); // 检查监听函数参数调用情况 expect(spyobj.setBar).toHaveBeenCalledWith('123'); expect(spyobj.setBar).toHaveBeenCalledWith('1', '2'); // bar变量值默认是不会保存的 expect(bar).toBeNull(); })});
  • and.callThrough方法可以让监听的方法返回值保留下来
describe('test spy ', function(){
var spyobj, bar = null; beforeEach(function(){
spyobj = {
setBar: function(val){
bar = val; } } spyOn(spyobj, 'setBar').and.callThrough(); spyobj.setBar('123'); spyobj.setBar('1', '2'); }); it('check spyobj invoke track', function(){
// bar变量此次保存了下来 expect(bar).toEqual('1'); })});
  • and.returnValue方法可以指定监听的方法返回值
describe('test spy ', function(){
var spyobj, bar = null, foo; beforeEach(function(){
spyobj = {
setBar: function(val){
bar = val; }, getBar: function(){
return bar; } } spyOn(spyobj, "getBar").and.returnValue('1'); spyobj.setBar('123'); foo = spyobj.getBar(); }); it('check spyobj invoke track', function(){
expect(bar).toEqual('123'); // returnValue改变了原先的setBar方法设置的值 expect(foo).toEqual('1'); })});
  • and.callFake方法可以伪造监听的方法返回值,通过一个自定义函数
describe('test spy ', function(){
var spyobj, bar = null, foo; beforeEach(function(){
spyobj = {
setBar: function(val){
bar = val; }, getBar: function(){
return bar; } } spyOn(spyobj, "getBar").and.callFake(function(){
return 'yicai'; }); spyobj.setBar('123'); foo = spyobj.getBar(); }); it('check spyobj invoke track', function(){
expect(bar).toEqual('123'); // callFake改变了原先的setBar方法设置的值 expect(foo).toEqual('yicai'); })});
  • and.throwError方法可以让监听方法执行之后返回一个错误信息,可以通过toThrowError来适配
describe('test spy ', function(){
var spyobj, bar = null; beforeEach(function(){
spyobj = {
setBar: function(val){
bar = val; }, getBar: function(){
return bar; } } spyOn(spyobj, "setBar").and.throwError('error'); }); it('check spyobj invoke track', function(){
expect(function(){
spyobj.setBar(); }).toThrowError('error'); })});
  • and.stub方法可以还原监听方法的返回值
describe('test spy ', function(){
var spyobj, bar = null; beforeEach(function(){
spyobj = {
setBar: function(val){
bar = val; }, getBar: function(){
return bar; } } spyOn(spyobj, "setBar").and.callThrough(); }); it('check spyobj invoke track', function(){
spyobj.setBar('123'); expect(bar).toEqual('123'); spyobj.setBar.and.stub(); bar = null; spyobj.setBar('123'); expect(bar).toBe(null); })});
  • calls这里包含很多监听过程中的属性信息

    • .calls.any(),一次都没调用,则返回false,否则返回true
    • .calls.count(),返回监听函数调用的次数
    • .calls.argsFor(index),返回监听函数调用过程中传递的所有参数信息,index代表调用的索引数
    • .calls.allArgs(),返回监听函数调用过程中的所以参数信息,是一个数组,每一项代表一次调用传参信息
    • .calls.all(),返回监听函数调用过程中的所有信息,除了参数信息还包含this上下文信息
    • .calls.mostRecent(),返回监听函数最后一次调用的相关信息,除了参数还包含this上下文信息
    • .calls.first(),返回第一次调用监听函数的相关信息,除了参数还包含this上下文信息
    • .calls.reset(),清除监听函数调用信息,.calls.any()将返回false

下面以一个例子来说明,在访问监听函数上的calls属性时的信息

describe('test spy ', function(){
var spyobj, bar = null; beforeEach(function(){
spyobj = {
setBar: function(val){
bar = val; }, getBar: function(){
return bar; } } spyOn(spyobj, "setBar"); }); it('check spyobj invoke track', function(){
// 监听函数没调用过,则返回false expect(spyobj.setBar.calls.any()).toBe(false); spyobj.setBar('1'); spyobj.setBar('2', '4'); // 上面调用了2次 expect(spyobj.setBar.calls.count()).toEqual(2); // 分别获取上面调用两次时的入参信息,索引就是调用顺序 expect(spyobj.setBar.calls.argsFor(0)).toEqual(['1']); expect(spyobj.setBar.calls.argsFor(1)).toEqual(['2', '4']); // 获取所有调用时的入参信息 expect(spyobj.setBar.calls.allArgs()).toEqual([ ['1'], ['2', '4'] ]); // 获取所有调用信息,包括this上下文信息 expect(spyobj.setBar.calls.all()).toEqual([ {
object: spyobj, args: ['1'], returnValue: undefined }, {
object: spyobj, args: ['2','4'], returnValue: undefined } ]); // 获取最近一次调用的信息 expect(spyobj.setBar.calls.mostRecent()).toEqual({
object: spyobj, args: ['2', '4'], returnValue: undefined}); // 获取第一次调用的信息 expect(spyobj.setBar.calls.first()).toEqual({
object: spyobj, args: ['1'], returnValue: undefined}); // 清除监听函数调用信息 spyobj.setBar.calls.reset(); expect(spyobj.setBar.calls.any()).toBe(false); })});

注意,当在calls对象上调用all(),mostRecent(),first(),返回的object属性指向的是this上下文信息

  • createSpy,可以创建一个命名的监听函数
describe('test spy ', function(){
var spyobj, bar = null; beforeEach(function(){
spyobj = jasmine.createSpy('spyobj'); spyobj('1', '2'); }); it('check spyobj invoke track', function(){
expect(spyobj.and.identity()).toEqual('spyobj'); expect(spyobj.calls.any()).toBe(true); expect(spyobj.calls.count()).toEqual(1); expect(spyobj).toHaveBeenCalledWith('1', '2'); expect(spyobj.calls.mostRecent().args[0]).toEqual('1'); })});
  • createSpyObj,可以批量创建监听函数
describe('test spy ', function(){
var spyobj, bar = null; beforeEach(function(){
spyobj = jasmine.createSpyObj('spyobj', ['play', 'pause', 'stop', 'rewind']); spyobj.play(); spyobj.pause('1'); }); it('check spyobj invoke track', function(){
expect(spyobj.rewind.and.identity()).toEqual('spyobj.rewind'); expect(spyobj.play.calls.any()).toBe(true); expect(spyobj.stop.calls.any()).toBe(false); expect(spyobj.pause.calls.count()).toEqual(1); expect(spyobj.pause.calls.mostRecent().args[0]).toEqual('1'); })});

jasmine.any

检验变量是否匹配相关类型
describe("jasmine.any", function() {
it("matches any value", function() {
expect({}).toEqual(jasmine.any(Object)); expect(12).toEqual(jasmine.any(Number)); }); describe("when used with a spy", function() {
it("is useful for comparing arguments", function() {
var foo = jasmine.createSpy('foo'); foo(12, function() {
return true; }); expect(foo).toHaveBeenCalledWith(jasmine.any(Number), jasmine.any(Function)); }); });});

jasmine.objectContaining

检验对象是否包含某个`key/value`
describe("jasmine.objectContaining", function() {
var foo; beforeEach(function() {
foo = {
a: 1, b: 2, bar: "baz" }; }); it("matches objects with the expect key/value pairs", function() {
expect(foo).toEqual(jasmine.objectContaining({
bar: "baz" })); expect(foo).not.toEqual(jasmine.objectContaining({
c: 37 })); }); describe("when used with a spy", function() {
it("is useful for comparing arguments", function() {
var callback = jasmine.createSpy('callback'); callback({
bar: "baz" }); expect(callback).toHaveBeenCalledWith(jasmine.objectContaining({
bar: "baz" })); expect(callback).not.toHaveBeenCalledWith(jasmine.objectContaining({
c: 37 })); }); });});

jasmine.clock

jasmine的时钟
  • jasmine.clock().install(), 启动时钟控制

  • jasmine.clock().uninstall(), 停止时钟控制

  • jasmine.clock().tick, 让时钟往前走多少秒

  • jasmine.clock().mockDate, 可以根据传入的date来设置当前时间

下面以一个完整的例子来说明

describe('test jasmine.clock', function(){
var timecallback; beforeEach(function(){
timecallback = jasmine.createSpy('timecallback'); jasmine.clock().install(); }); afterEach(function(){
jasmine.clock().uninstall(); }) it('mock setTimeout clock ', function(){
setTimeout(function(){
timecallback(); }, 100); expect(timecallback).not.toHaveBeenCalled(); jasmine.clock().tick(101); expect(timecallback).toHaveBeenCalled(); }) it('mock setInterval clock ', function(){
setInterval(function(){
timecallback(); }, 100); expect(timecallback).not.toHaveBeenCalled(); jasmine.clock().tick(101); expect(timecallback.calls.count()).toEqual(1); jasmine.clock().tick(50); expect(timecallback.calls.count()).toEqual(1); jasmine.clock().tick(50); expect(timecallback.calls.count()).toEqual(2); }) it('mock date clock ', function(){
var baseTime = new Date(2013, 9, 23); jasmine.clock().mockDate(baseTime); jasmine.clock().tick(50); expect(new Date().getTime()).toEqual(baseTime.getTime() + 50); })})

jasmine异步支持

  • beforeEachit,包装的函数传入done参数,只有当done函数执行完成之后,beforeEach, it才算执行完成

  • jasmine.DEFAULT_TIMEOUT_INTERVAL, 默认是5秒之后就超时,可以修改这个超时时间

下面以一个完整的例子来说jasmine中异步操作

describe('test asynchonous ', function(){
var value = 0, originalTimeout; beforeEach(function(done){
originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL; // 设置jasmine超时时间为10秒 jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000; setTimeout(function(){
value += 1; // 只有执行done函数,后面的it才会执行 done(); }, 200); }); afterEach(function(){
// 还原jasmine超时时间 jasmine.DEFAULT_TIMEOUT_INTERVAL = originalTimeout; }) it('expect value toEqual 1', function(done){
setTimeout(function(){
expect(value).toEqual(1); // 只有执行这个,后面的it才会执行 done(); }, 9000); }); it('until above spec complete ', function(){
expect(value).toBe(2); });})

相关链接

转载地址:http://xkcgo.baihongyu.com/

你可能感兴趣的文章
Spring Ioc的实现----------用idea实现控制反转
查看>>
Java基础——变量
查看>>
跨域获取图片并自行上传保存
查看>>
Junit,Mockito,PowerMockito 进行单元测试
查看>>
要通过面试,Lamdba要了解多少?
查看>>
vim介绍、颜色显示和移动光标、一般模式下复制、剪切和粘贴
查看>>
PHP安装
查看>>
mysql用户管理-常用sql-数据库备份恢复
查看>>
springcloud应用程序上下文层次结构
查看>>
UI2Code智能生成Flutter代码--整体设计篇
查看>>
<java8>Java8 Optional 的使用
查看>>
教你怎样使用Spring Boot开发邮件系统?
查看>>
JAVA springboot微服务b2b2c电子商务系统 (五)springboot整合 beatlsql
查看>>
沙龙报名 | 探索新零售时代的数字化创新
查看>>
spring security中当前用户信息
查看>>
[Golang软件推荐] RSA公私钥加解密(解决Golang私钥加密公钥解密问题)
查看>>
html-meta http-equiv设置网页指定时间跳转
查看>>
python 入门
查看>>
如何防止http请求数据被篡改
查看>>
MyEclipse 2013集成JRebel
查看>>