5、Matchers
Jasmine定义了多个Matchers,用来测试一些变量是否通过。
常见的有:
- toBe():判断两个变量是否全等,类似于“===”;
- toNotBe():与上一个相反,判断两个变量是否不全等,类似于“!==”;
- toBeDefined():检查变量或属性是否已声明且赋值;
- toBeUndefined():与上一个相反;
- toBeNull():判断变量是否为null;
- toBeTruthy():判断变量如果转换为布尔值,是否为true;
- toBeFalsy():与上一个相反;
- toBeLessThan():与数值比较,是否小于;
- toBeGreaterThan():与数值比较,是否大于;
- toEqual():判断变量是否相等,相当于“==”;
- toContain():判断一个数组中是否包含元素(值)。只能用于数组,不能用于对象;
- toBeCloseTo():数值比较时定义精度,先四舍五入后再比较;
- toMatch():按正则表达式匹配;
- toNotMatch():与上一个相反;
- toThrow():检验一个函数是否会抛出一个错误。
- 注意:任何Matcher都能通过在expect调用Matcher前加上not来实现一个否定的断言(expect(a).not().toBe(false);)。
常见的Matchers使用代码如下:
describe("Included matchers:", function() { it("The 'toBe' matcher compares with ===", function() { //toBe()类似于"===" var a = 12; var b = a; expect(a).toBe(b);//通过 expect(a).not.toBe(null);//通过,因为a!==null }); describe("The 'toEqual' matcher", function() { //toEqual()类似于"==" it("works for simple literals and variables", function() { var a = 12; expect(a).toEqual(12);//通过 }); it("should work for objects", function() { var foo = { a: 12, b: 34 }; var bar = { a: 12, b: 34 }; expect(foo).toEqual(bar);//通过,两个对象属性和值都一样 }); }); it("The 'toMatch' matcher is for regular expressions", function() { //toMatch()用于匹配正则表达式 var message = "foo bar baz"; expect(message).toMatch(/bar/);//通过,参数可以是正则表达式 expect(message).toMatch("bar");//通过,参数可以是字符串 expect(message).not.toMatch(/quux/);//通过,因为toMatch()匹配不到/quux/ }); it("The 'toBeDefined' matcher compares against `undefined`", function() { //toBeDefined()判断参数是否定义 var a = { foo: "foo" }; expect(a.foo).toBeDefined(); expect(a.bar).not.toBeDefined(); }); it("The `toBeUndefined` matcher compares against `undefined`", function() { //toBeUndefined()判断参数是否为undefined var a = { foo: "foo" }; expect(a.foo).not.toBeUndefined(); expect(a.bar).toBeUndefined(); }); it("The 'toBeNull' matcher compares against null", function() { //toBeNull()判断参数是否为空 var a = null; var foo = "foo"; expect(null).toBeNull(); expect(a).toBeNull(); expect(foo).not.toBeNull(); }); it("The 'toBeTruthy' matcher is for boolean casting testing", function() { //toBeTruthy()判断参数转化为布尔值时是否为true var a, foo = "foo"; expect(foo).toBeTruthy();//通过,foo变量转变为true expect(a).not.toBeTruthy(); }); it("The 'toBeFalsy' matcher is for boolean casting testing", function() { //toBeFalsy()判断参数转化为布尔值时是否为false var a, foo = "foo"; expect(a).toBeFalsy(); expect(foo).not.toBeFalsy(); }); it("The 'toContain' matcher is for finding an item in an Array", function() { //toContain()判断元素是否存在于数组内。不适用于对象 var a = ["foo", "bar", "baz"]; expect(a).toContain("bar"); expect(a).not.toContain("quux"); }); it("The 'toBeLessThan' matcher is for mathematical comparisons", function() { //toBeLessThan()判断实际值是否小于期望值 var pi = 3.1415926, e = 2.78; expect(e).toBeLessThan(pi); expect(pi).not.toBeLessThan(e); }); it("The 'toBeGreaterThan' matcher is for mathematical comparisons", function() { //toBeGreaterThan()判断实际值是否大于期望值 var pi = 3.1415926, e = 2.78; expect(pi).toBeGreaterThan(e); expect(e).not.toBeGreaterThan(pi); }); it("The 'toBeCloseTo' matcher is for precision math comparison", function() { //toBeCloseTo()数值比较时定义精度,先四舍五入后再比较 var pi = 3.1415926, e = 2.78; expect(pi).not.toBeCloseTo(e, 2); expect(pi).toBeCloseTo(e, 0); }); it("The 'toThrow' matcher is for testing if a function throws an exception", function() { //toThrow()判断函数是否会抛出一个错误 var foo = function() { return 1 + 2; }; var bar = function() { return a + 1; }; expect(foo).not.toThrow(); expect(bar).toThrow(); }); it("The 'toThrowError' matcher is for testing a specific thrown exception", function() { //toThrowError()判断函数是否抛出一个特别的错误,以下四种都能够通过测试 var foo = function() { throw new TypeError("foo bar baz"); }; expect(foo).toThrowError("foo bar baz"); expect(foo).toThrowError(/bar/); expect(foo).toThrowError(TypeError); expect(foo).toThrowError(TypeError, "foo bar baz"); }); });
6、自定义Matchers
当然,用户可以自定义Matchers。在beforeEach()
或it()
函数里调用Jasmine.addMatchers()
,其中可以传递一个参数expected
作为测试值,而实际值则保存在this.actual
中,代码如下:
describe("This is a suite", function() { beforeEach(function(){ var a = 'abc'; this.addMatchers({ toBeTrue : function(expected){ return this.actual==expected; } }); }); it("This is a specs1", function() { expect(a).toBeTrue('abc'); }); });
代码在beforeEach()中调用this.addMatchers()定义了一个Matchers。定义了ToBeTrue(),传递一个参数expected与实际值作比较。
后面调用该Matchers时,代码expect(a).toBeTrue('abc');中,a则为实际值(this.actual),而“abc”则为参数expected。
该定义的Matchers与原有的toEqual()类似。
7、禁用Suites
通过调用xdescribe()
函数可以禁用Suites。代码执行时,这些Suites以及里面的任何spec都将跳过,因而他们的结果也不会出现在最终的输出结果中。例如:
xdescribe("A spec", function() { var foo; beforeEach(function() { foo = 0; foo += 1; }); it("is just a function, so it can contain any code", function() { expect(foo).toEqual(1); }); });
输出结果如图:
8、挂起Specs
被挂起的spec不会执行。但是他们的名字仍会显示在pending的结果集中。
声明挂起的方式有三种:
- spec可以使用
xit()
来声明挂起; - spec声明时不添加任何函数体也可以在结果中达到挂起的效果;
- 如果你在spec体内的任何位置调用pending()函数,不管那个断言通过与否,该spec都将被挂起。当Suites结束后,pending所传递的字符串将被作为挂起的理由而显示。
例如:
describe("Pending specs", function() { xit("can be declared 'xit'", function() { //使用xit()函数挂起 expect(true).toBe(false); }); it("can be declared with 'it' but without a function"); //使用空函数体将spec挂起 it("can be declared by calling 'pending' in the spec body", function() { expect(true).toBe(false); pending('this is why it is pending'); //调用pending()将其挂起 }); });
最终显示结果为:
9、this
关键字
除了在describe()
声明变量外,另外一个在beforeEach()
,it()
,afterEach()
之间共享变量的方法是使用this关键字。每一个spec的beforeEach()
,it()
,afterEach()
拥有相同的在下个spec的beforeEach()
,it()
,afterEach()
执行之前会延迟置空的空对象this
。
代码如下:
describe("A spec", function() { beforeEach(function() { this.foo = 0; }); it("can use the `this` to share state", function() { expect(this.foo).toEqual(0); this.bar = "test pollution?"; }); it("prevents test pollution by having an empty `this` created for the next spec", function() { expect(this.foo).toEqual(0); expect(this.bar).toBe(undefined); }); });
代码在每个spec之前声明this.foo
并赋值,在其it()
函数里能够共享该变量。而在it()
函数里声明的this.bar
,在下一个spec执行时无法获得,此时两者的this
关键字所指向的并不一致。
更多教程:Jasmine - 文档(二)