Jasmine
Jasmine is a behavior-driven development framework for testing JavaScript code. It does not depend on any other JavaScript frameworks. It does not require a DOM. And it has a clean, obvious syntax so that you can easily write tests. This guide is running against Jasmine version 2.3.0.
上面是官网的介绍。总体来说,大致意思就是:Jasmine是用于测试JavaScript代码的行为驱动开发框架。Jasmine 是一个简易的JS单元测试框架。它不依赖于任何其他的JavaScript框架。它不需要一个DOM。它有一个干净,明显的语法让您可以轻松地编写测试。
简单介绍
- 首先任何一个测试用例以describe函数来定义,它有两参数,第一个用来描述测试大体的中心内容,第二个参数是一个函数,里面写一些真实的测试代码
-
it
是用来定义单个具体测试任务,也有两个参数,第一个用来描述测试内容,第二个参数是一个函数,里面存放一些测试方法 -
expect
主要用来计算一个变量或者一个表达式的值,然后用来跟期望的值比较或者做一些其它的事件 *beforeEach
与afterEach
主要是用来在执行测试任务之前和之后做一些事情,上面的例子就是在执行之前改变变量的值,然后在执行完成之后重置变量的值
ng的单元你测试
因为ng本身框架的原因,模块都是通过di来加载以及实例化的,所以为了方便配合jasmine来编写测试脚本,所以官方提供了angular-mock.js的一个测试工具类来提供模块定义,加载,注入等.
require('ngMocks');
inject里面就是利用angular.inject方法创建的一个内置的依赖注入实例,然后里面的模块注入跟普通ng模块里的依赖处理是一样的.
beforeEach(mocks.inject(function($injector) {
authService = $injector.get('ArchiveOutAuthService');
}));
禁用Suites
Suites可以被Disabled。在describe函数名之前添加x即可将Suite禁用。 被Disabled的Suites在执行中会被跳过,该Suite的结果也不会显示在结果集中。
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);
});
});
可以使用的单元测试的方法
常用
-
tobe() (The 'toBe' matcher compares with ===)
expect(a).toBe(true);
expect(false).not.toBe(true);
-
toEqual() (The 'toEqual' matcher )
- (works for simple literals and variables)
var a = 12; expect(a).toEqual(12); - (should work for objects)
var bar = { a: 12, b: 34 }; expect(bar).toEqual(bar);
- (works for simple literals and variables)
-
toMatch() (The 'toMatch' matcher is for regular expressions)
var message = "foo bar baz";
expect(message).toMatch(/bar/);
-
toBeDefined() (The 'toBeDefined' matcher compares against
undefined
)expect(a.foo).toBeDefined(); expect(a.bar).not.toBeDefined();
-
toBeUndefined() (The
toBeUndefined
matcher compares againstundefined
)expect(a.foo).not.toBeUndefined();
-
toBeNull() (The 'toBeNull' matcher compares against null)
expect(null).toBeNull();
-
toBeTruthy() (如果转换为布尔值,是否为true)
expect(foo).toBeTruthy(); || expect(a).not.toBeTruthy();
// 数值可以换转为true或者false 比如expect(1).toBeTruthy();
-
toBeFalsy() (如果转换为布尔值,是否为false)
expect(a).toBeFalsy();
-
toContain() (The 'toContain' matcher is for finding an item in an Array) 数组中是否包含
//数组中是否包含元素(值)。只能用于数组,不能用于对象
var a = ["foo", "bar", "baz"]; expect(a).toContain("bar");
数字
var pi = 3.1415926,
e = 2.78;
-
toBeLessThan() (The 'toBeLessThan' matcher is for mathematical comparisons) 数值比较,少于
expect(e).toBeLessThan(pi); expect(pi).not.toBeLessThan(e);
-
toBeGreaterThan() (The 'toBeGreaterThan' matcher is for mathematical comparisons) 数值比较,大于
expect(pi).toBeGreaterThan(e);
-
toBeCloseTo() (The 'toBeCloseTo' matcher is for precision math comparison)
//两个数值是否接近,这里接近的意思是将pi和e保留一定小数位数后,是否相等。(一定小数位数:默认为2,也可以手动指定) //数值比较时定义精度,先四舍五入后再比较
expect(pi).not.toBeCloseTo(e, 2); expect(pi).toBeCloseTo(e, 0);
-
toThrow() (检验一个函数是否会抛出一个错误)
var bar = function() { return a + 1; };
expect(bar).toThrow();
-
toThrowError() (期望a方法抛出异常,异常信息可以是字符串、正则表达式、错误类型以及错误类型和错误信息 )
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");
jasmine.objectContaining
用于检测实际Object值中是否存在特定key/value对。
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
}));
});
jasmine.arrayContaining
用于检测实际Array值中是否存在特定值。
var foo;
beforeEach(function() {
foo = [1, 2, 3, 4];
});
it("matches arrays with some of the values", function() {
expect(foo).toEqual(jasmine.arrayContaining([3, 1]));
expect(foo).not.toEqual(jasmine.arrayContaining([6]));
});
高级使用
-
Spy
Spy能监测任何function的调用和方法参数的调用痕迹。需使用2个特殊的Matcher:
- toHaveBeenCalled:可以检查function是否被调用过,
- toHaveBeenCalledWith: 可以检查传入参数是否被作为参数调用过。
-
spyOn
使用spyOn(obj,'function')来为obj的function方法声明一个Spy。不过要注意的一点是,对Spy函数的调用并不会影响真实的值。
spyOn(foo, 'setBar'); expect(foo.setBar).toHaveBeenCalledWith(123);
- spyOn(foo, "getBar").and.returnValue(745);
- spyOn(foo, "getBar").and.callFake(function() { return 1001; });
- spyOn(foo, "setBar").and.throwError("quux");
-
调用次数
beforeEach(function() { foo = { setBar: function(value) { bar = value; } };
spyOn(foo, 'setBar'); });
-
用法1:
expect(foo.setBar.calls.any()).toEqual(false);
foo.setBar();
expect(foo.setBar.calls.any()).toEqual(true);
-
用法2:
foo.setBar(); foo.setBar();
expect(foo.setBar.calls.count()).toEqual(2);
-
-
异步支持(Asynchronous Support)
调用beforeEach,it或者afterEach时,可以添加一个可选参数(Function类型,在官方文档的例子中该参数为done)。当done函数被调用,表明异步操作的回调函数调用成功;否则如果没有调用done,表明异步操作的回调函数调用失败,则该Spec不会被调用,且会因为超时退出。 Jasmine等待异步操作完成的默认时间是5s,如果5s内异步操作没有完成,则Spec会因为超时退出。超时时间也可以通过全局的jasmine.DEFAULTTIMEOUTINTERVAL修改。
var value;
// setTimeout代表一个异步操作。
beforeEach(function(done) {
setTimeout(function() {
value = 0;
// 调用done表示回调成功,否则超时。
done();
}, 1);
});
// 如果在beforeEach中的setTimeout的回调中没有调用done,最终导致下面的it因超时而失败。
it("should support async execution of test preparation and expectations", function(done) {
value++;
expect(value).toBeGreaterThan(0);
done();
});