Jasmine基础语法

时间:2021-04-09 14:37:01

简介

Jasmine 是JavaScript的测试框架,它不依赖其他框架,也不依赖DOM,更重要的是它语法简单。以下实例都是基于Jasmine 2.5.2的,并且来自官网:https://jasmine.github.io/edge/introduction

安装

安装推荐使用npm安装,需要本地和全局安装。

#本地安装
npm install -D jasmine #全局安装
npm install -g jasmine #用jasmine初始化项目
jasmine init #可以生成示例
jasmine examples #运行测试套件
jasmine

基本组成

Jasmine可以概括为DistributionSpecsExpectations依次嵌套组成的:

Distribution

对应全局函数describe,是实现测试套件的开始。describe接受两个参数:stringfunctionstring是这个测试套件的标题,function就是实现这个测试套件。可以嵌套多个Distribution

Specs

对应全局函数it,放在describefunction参数内,将Distribution分拆成各个测试规格。it方法也接受stringfunctionstring是作为这个Specs的描述,而function就是放测试期望(Expectations)。Expectations可以在it中存在多个,只要有一个Expectations是测试不通过的,整个Specs都是不通过。

Expectations

Expectations的构建需要使用全局方法expect,它通过链式Matcher方法来比较实际值是否和预期值一致,如果一致就是测试通过。

所以Distribution一般都是这种结构的:

describe("我是describe的string", function() {
var a; it("我是it的string", function() {
a = true; expect(a).toBe(true);//可以换成false看下输出什么
});
});

目前Distribution和Specs的作用可以说是将测试套件模块化,不然 “ false expectations “ 描述不通过的时候都不知道找哪里。

Matchers

都是作为Expectations的链式调用而使用,用于比较期望值和实际值。其中可以使用not进行期望结果的否定。

describe("包括的Matchers:", function() {
it("'toBe' matcher 比较时使用 ===", function() {
var a = 12;
var b = a; expect(a).toBe(b);
expect(a).not.toBe(null);
}); describe("'toEqual' matcher", function() { it("适合简单的文本和变量", function() {
var a = 12;
expect(a).toEqual(12);
}); it("也适用于对象的深度比较", function() {
var foo = {
a: 12,
b: 34
};
var bar = {
a: 12,
b: 34
};
expect(foo).toEqual(bar);
});
}); it("'toMatch' matcher 是使用正则表达式", function() {
var message = "foo bar baz"; expect(message).toMatch(/bar/);
expect(message).toMatch("bar");
expect(message).not.toMatch(/quux/);
}); it("'toBeDefined' matcher 是将期望和undefined进行比较", function() {
var a = {
foo: "foo"
}; expect(a.foo).toBeDefined();
expect(a.bar).not.toBeDefined();
}); it("The `toBeUndefined` matcher 是将期望和undefined进行比较", function() {
var a = {
foo: "foo"
}; expect(a.foo).not.toBeUndefined();
expect(a.bar).toBeUndefined();
}); it("'toBeNull' matcher 是将期望和null进行比较", function() {
var a = null;
var foo = "foo"; expect(null).toBeNull();
expect(a).toBeNull();
expect(foo).not.toBeNull();
}); it("'toBeTruthy' matcher 是进行Boolean转换后与true进行比较", function() {
var a, foo = "foo"; expect(foo).toBeTruthy();
expect(a).not.toBeTruthy();
}); it("'toBeFalsy' matcher 是进行Boolean转换后与false进行比较", function() {
var a, foo = "foo"; expect(a).toBeFalsy();
expect(foo).not.toBeFalsy();
}); describe("'toContain' matcher", function() {
it("适用于数组的寻值", function() {
var a = ["foo", "bar", "baz"]; expect(a).toContain("bar");
expect(a).not.toContain("quux");
}); it("也使用于字符串内找单词", function() {
var a = "foo bar baz"; expect(a).toContain("bar");
expect(a).not.toContain("quux");
});
}); it("'toBeLessThan' matcher 进行小于的数值期望比较", function() {
var pi = 3.1415926,
e = 2.78; expect(e).toBeLessThan(pi);
expect(pi).not.toBeLessThan(e);
}); it("'toBeGreaterThan' matcher 进行大于的数值期望比较", function() {
var pi = 3.1415926,
e = 2.78; expect(pi).toBeGreaterThan(e);
expect(e).not.toBeGreaterThan(pi);
}); it("'toBeCloseTo' matcher 精确数学比较,没看懂比较结果的依据", function() {
var pi = 3.1415926,
e = 2.78; expect(pi).not.toBeCloseTo(e, 2);
expect(pi).toBeCloseTo(e, 0);
}); it("'toThrow' matcher 期望函数会抛出异常", function() {
var foo = function() {
return 1 + 2;
};
var bar = function() {
return a + 1;
};
var baz = function() {
throw 'what';
}; expect(foo).not.toThrow();
expect(bar).toThrow();//不抛异常也可以用`toThrow`,不过不能有参数
expect(baz).toThrow('what');//抛new Error()时,这里的参数也需要是new Error() }); it("'toThrowError' matcher 用于测试特定抛出异常", function() {
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");
});
});

除了使用Matchers进行期望比较外,可以直接使用全局方法fail否定期望:

describe("使用fail", function() {
var foo = function(x, callBack) {
if (x) {
callBack();
}
}; it("调用fail就是否定这个spec", function() {
foo(false, function() {
fail("Callback has been called");
});
});
});

Setup and Teardown(就是钩子)

有四个全局方法作为钩子的:beforeEach, afterEach, beforeAll, 和 afterAll。

beforeEach和afterEach

beforeEach/afterEach会在describe中的每个it的方法参数的调用前/后都会执行一次。粗暴的理解就是说在describe内执行一次或多次,在it内执行一次。

describe("A spec using beforeEach and afterEach", function() {
var foo = 0; beforeEach(function() {
foo += 1;
}); afterEach(function() {
foo = 0;
}); it("is just a function, so it can contain any code", function() {
expect(foo).toEqual(1);
}); it("can have more than one expectation", function() {
expect(foo).toEqual(1);
expect(true).toEqual(true);
});
});

beforeAll和afterAll

beforeAll/afterAll会在describe中的全部it的方法参数的调用前/后只执行一次。粗暴的理解就是说在describe内只执行一次。

describe("A spec using beforeAll and afterAll", function() {
var foo; beforeAll(function() {
foo = 1;
}); afterAll(function() {
foo = 0;
}); it("sets the initial value of foo before specs run", function() {
expect(foo).toEqual(1);
foo += 1;
}); it("does not reset foo between specs", function() {
expect(foo).toEqual(2);
});
});

this

可以在beforeEach和afterEach的this中定义属性传递it的this。注意这里传递值的时候是值传递,每个it中的this都是相互独立的,改变it中this的属性并不会作用于其他it,也不会影响到beforeEach和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);
});
});

嵌套describe

describe可以嵌套,并且也说过beforeEach/afterEach会在describe中的每个it的方法参数的调用前/后都会执行一次,所以在嵌套时也会有类似作用域的情况:

describe("A spec", function() {
var foo = 0; beforeEach(function() { foo += 1;
}); it("is just a function, so it can contain any code", function() {
expect(foo).toEqual(1);
}); it("can have more than one expectation", function() {
expect(foo).toEqual(2);
expect(true).toEqual(true);
}); describe("nested inside a second describe", function() {
var bar; beforeEach(function() {
bar = 3;
}); it("can reference both scopes as needed", function() {
expect(foo).toEqual(bar);
});
});
});

Pending

测试套件有时想写上去但是还不用,就要使用xdescribe方法了,这些套件都会在运行的时候跳过:

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);
});
});

当然也可以只是禁用Specs,那就可以用

  • xit
  • it不传递方法参数;
  • 使用全局的pending方法;
describe("A spec", function() {
xit("can be declared 'xit'", function() {
expect(true).toBe(false);
}); it("can be declared with 'it' but without a function"); it("can be declared by calling 'pending' in the spec body", function() {
expect(true).toBe(false);
pending('this is why it is pending');
});
});

Spies

上面的内容可以说就是对值的测试,Jasmine还可以使用spy对函数的调用情况进行测试。spy只能在beforeEach、beforeAll或者spec内定义,并且会在各个spec使用后销毁(这个特性很重要)spy还有自己的matchers。分别是:

  • toHaveBeenCalled:期望函数被调用;
  • toHaveBeenCalledTimes:期望函数的调用次数;
  • toHaveBeenCalledWith:期望函数的调用参数;

没有用spyOn注册的方法是不能使用这些matchers的。

describe("A spy", function() {
var foo, bar = null; beforeEach(function() {
foo = {
setBar: function(value) {
bar = value;
}
}; spyOn(foo, 'setBar'); foo.setBar(123);
foo.setBar(456, 'another param');
}); it("tracks that the spy was called", function() {
expect(foo.setBar).toHaveBeenCalled();
}); it("tracks that the spy was called x times", function() {
expect(foo.setBar).toHaveBeenCalledTimes(2);
}); it("tracks all the arguments of its calls", function() {
expect(foo.setBar).toHaveBeenCalledWith(123);
expect(foo.setBar).toHaveBeenCalledWith(456, 'another param');
}); it("stops all execution on a function", function() {
expect(bar).toBeNull();
});
});
  • 注意:spyOn方法的参数必须是(object,methodName);
  • 注意:最后一个spec,expect(bar).toBeNull();,明明已经调用了setBar了,为什么bar还是null的呢?这是因为使用spyOn注册后的方法调用默认都是模拟调用的,并不会执行实际的代码。

and属性的链式操作

spyOn定义后还可以使用链式操作代理函数的执行。

and.callThrough

函数执行的时候会执行实际的代码。其实除了and.stub,其他and属性的方法都会调用and.callThrough

describe("A spy, when configured to call through", function() {
var foo, bar, fetchedBar; beforeEach(function() {
foo = {
setBar: function(value) {
bar = value;
},
getBar: function() {
return bar;
}
}; spyOn(foo, 'getBar').and.callThrough(); foo.setBar(123);
fetchedBar = foo.getBar();
}); it("tracks that the spy was called", function() {
expect(foo.getBar).toHaveBeenCalled();
}); it("should not affect other functions", function() {
expect(bar).toEqual(123);
}); it("when called returns the requested value", function() {
expect(fetchedBar).toEqual(123);
});
});

and.returnValue(value)

注册的方法不会执行代码,而是直接返回and.returnValue的参数,不过注册对象的其他方法都得到会实际执行。

describe("A spy, when configured to fake a return value", function() {
var foo, bar, fetchedBar ,otherTest; beforeEach(function() {
foo = {
setBar: function(value) {
bar = value;
},
getBar: function() {
return bar;
}
}; spyOn(foo, "getBar").and.returnValue(745); foo.setBar(123);
fetchedBar = foo.getBar();
}); it("tracks that the spy was called", function() {
expect(foo.getBar).toHaveBeenCalled();
}); it("should not affect other functions", function() {
expect(bar).toEqual(123);
}); it("when called returns the requested value", function() {
expect(fetchedBar).toEqual(745);
expect(otherTest).toBeUndefined();
});
});

and.returnValues(...value)

and.returnValue类似,不过可以接受多个参数,调用函数的时候依次返回这些参数,最后会返回undefined

describe("A spy, when configured to fake a series of return values", function() {
var foo, bar; beforeEach(function() {
foo = {
setBar: function(value) {
bar = value;
},
getBar: function() {
return bar;
}
}; spyOn(foo, "getBar").and.returnValues("fetched first", "fetched second"); foo.setBar(123);
}); it("tracks that the spy was called", function() {
foo.getBar(123);
expect(foo.getBar).toHaveBeenCalled();
}); it("should not affect other functions", function() {
expect(bar).toEqual(123);
}); it("when called multiple times returns the requested values in order", function() {
expect(foo.getBar()).toEqual("fetched first");
expect(foo.getBar()).toEqual("fetched second");
expect(foo.getBar()).toBeUndefined();
});
});

and.callFake(function)

and.returnValue是直接返回值,and.callFake就是直接使用一个function代替:

describe("A spy, when configured with an alternate implementation", function() {
var foo, bar, fetchedBar; beforeEach(function() {
foo = {
setBar: function(value) {
bar = value;
},
getBar: function() {
return bar;
}
}; spyOn(foo, "getBar").and.callFake(function(arguments) {
return 1001;
}); foo.setBar(123);
fetchedBar = foo.getBar();
}); it("tracks that the spy was called", function() {
expect(foo.getBar).toHaveBeenCalled();
}); it("should not affect other functions", function() {
expect(bar).toEqual(123);
}); it("when called returns the requested value", function() {
expect(fetchedBar).toEqual(1001);
});
});

and.throwError(error)

直接让方法抛出异常。

describe("A spy, when configured to throw an error", function() {
var foo, bar; beforeEach(function() {
foo = {
setBar: function(value) {
bar = value;
},
getBar: function() {
return bar;
}
}; spyOn(foo, "getBar").and.throwError("quux");
foo.setBar(123);
}); it("throws the value", function() {
expect(foo.getBar).toThrowError("quux");
});
it("set bar", function() {
expect(bar).toBe(123);
});
});

and.stub()

去除方法的代理行为。

describe("A spy", function() {
var foo, bar = null; beforeEach(function() {
foo = {
setBar: function(value) {
bar = value;
}
}; spyOn(foo, 'setBar').and.callThrough();
}); it("can call through and then stub in the same spec", function() {
foo.setBar(123);
expect(bar).toEqual(123); foo.setBar.and.stub();
bar = null; foo.setBar(123);
expect(bar).toBe(null);
});
});

calls属性

经过spyOn方法注册后的方法都会有个calls属性跟踪函数使用情况,先定义describe

describe("A spy", function() {
var foo, bar = null; beforeEach(function() {
foo = {
setBar: function(value) {
bar = value;
}
}; spyOn(foo, 'setBar');
}); //...all it });

calls.any()

如果函数没有执行就会返回false,反之,执行了一次就会返回true

 it("tracks if it was called at all", function() {
expect(foo.setBar.calls.any()).toEqual(false); foo.setBar(); expect(foo.setBar.calls.any()).toEqual(true);
});

calls.count()

返回函数的调用次数。

 it("tracks the number of times it was called", function() {
expect(foo.setBar.calls.count()).toEqual(0); foo.setBar();
foo.setBar(); expect(foo.setBar.calls.count()).toEqual(2);
});

calls.argsFor(index)

返回第index次调用时的参数。

  it("tracks the arguments of each call", function() {
foo.setBar(123);
foo.setBar(456, "baz"); expect(foo.setBar.calls.argsFor(0)).toEqual([123]);
expect(foo.setBar.calls.argsFor(1)).toEqual([456, "baz"]);
});

calls.allArgs()

返回所有函数调用时的参数。

  it("tracks the arguments of all calls", function() {
foo.setBar(123);
foo.setBar(456, "baz"); expect(foo.setBar.calls.allArgs()).toEqual([[123],[456, "baz"]]);
});

calls.all()

返回全部函数调用时的信息,如上下文(this)、参数列表和返回值。如果只有一个就是对象,多个就是数组。

  it("has a shortcut to the most recent call", function() {
foo.setBar(123);
foo.setBar(456, "baz"); expect(foo.setBar.calls.mostRecent()).toEqual({object: foo, args: [456, "baz"], returnValue: undefined});
});

calls.mostRecent()/calls.first()

返回最后一次/第一次函数调用时的信息。

  it("has a shortcut to the most recent call", function() {
foo.setBar(123);
foo.setBar(456, "baz"); expect(foo.setBar.calls.mostRecent()).toEqual({object: foo, args: [456, "baz"], returnValue: undefined});
expect(foo.setBar.calls.first()).toEqual({object: foo, args: [123], returnValue: undefined});
});

calls.reset()

重置所有的调用信息。

describe("A spy", function() {
var foo, bar = null; beforeEach(function() {
foo = {
setBar: function(value) {
bar = value;
}
}; spyOn(foo, 'setBar');
}); it("can be reset", function() {
foo.setBar(123);
foo.setBar(456, "baz"); expect(foo.setBar.calls.any()).toBe(true); foo.setBar.calls.reset(); expect(foo.setBar.calls.any()).toBe(false); foo.setBar(123);
foo.setBar(456, "baz"); expect(foo.setBar.calls.any()).toBe(true);
});
});

假函数

可以使用createSpycreateSpyObj创建假函数,可以时Spies的全部功能,但是假函数内部并没有可以执行的代码,这种方式经常会用在对JavaScript中的对象的测试。

createSpy

创建一个假函数。

describe("A spy, when created manually", function() {
var whatAmI; beforeEach(function() {
whatAmI = jasmine.createSpy('whatAmI'); whatAmI("I", "am", "a", "spy");
}); it("is named, which helps in error reporting", function() {
expect(whatAmI.and.identity()).toEqual('whatAmI');
}); it("tracks that the spy was called", function() {
expect(whatAmI).toHaveBeenCalled();
}); it("tracks its number of calls", function() {
expect(whatAmI.calls.count()).toEqual(1);
}); it("tracks all the arguments of its calls", function() {
expect(whatAmI).toHaveBeenCalledWith("I", "am", "a", "spy");
}); it("allows access to the most recent call", function() {
expect(whatAmI.calls.mostRecent().args[0]).toEqual("I");
});
});

createSpyObj

可以通过创建对象,并添加方法的形式创建多个假函数。

describe("Multiple spies, when created manually", function() {
var tape; beforeEach(function() {
tape = jasmine.createSpyObj('tape', ['play', 'pause', 'stop', 'rewind']); tape.play();
tape.pause();
tape.rewind(0);
}); it("creates spies for each requested function", function() {
expect(tape.play).toBeDefined();
expect(tape.pause).toBeDefined();
expect(tape.stop).toBeDefined();
expect(tape.rewind).toBeDefined();
}); it("tracks that the spies were called", function() {
expect(tape.play).toHaveBeenCalled();
expect(tape.pause).toHaveBeenCalled();
expect(tape.rewind).toHaveBeenCalled();
expect(tape.stop).not.toHaveBeenCalled();
}); it("tracks all the arguments of its calls", function() {
expect(tape.rewind).toHaveBeenCalledWith(0);
});
});

Matching

值的类型期望。

jasmine.any(constructor)

进行类型检测,可以传入构造函数或在类名。

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');
class O{}; var o = new O();
foo(12, o , function(){}); expect(foo).toHaveBeenCalledWith(jasmine.any(Number), jasmine.any(O) , jasmine.any(Function));
});
});
});

jasmine.anything()

只要不是null或在undefined就可以。

describe("jasmine.anything", function() {
it("matches anything", function() {
expect(null).not.toEqual(jasmine.anything());
expect(undefined).not.toEqual(jasmine.anything());
expect(1).toEqual(jasmine.anything());
});
});

jasmine.objectContaining(object)

期望能找到object中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.arrayContaining(array)

期望array是子数组。

describe("jasmine.arrayContaining", function() {
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]));
}); describe("when used with a spy", function() {
it("is useful when comparing arguments", function() {
var callback = jasmine.createSpy('callback'); callback([1, 2, 3, 4]); expect(callback).toHaveBeenCalledWith(jasmine.arrayContaining([4, 2, 3]));
expect(callback).not.toHaveBeenCalledWith(jasmine.arrayContaining([5, 2]));
});
});
});

jasmine.stringMatching(string / RegExp)

期望string是子串(不局限于单词),或者RegExp能匹配到。

describe('jasmine.stringMatching', function() {
it("matches as a regexp", function() {
expect({foo: 'bar'}).toEqual({foo: jasmine.stringMatching(/^bar$/)});
expect({foo: 'foobarbaz'}).toEqual({foo: jasmine.stringMatching('bar')});
}); describe("when used with a spy", function() {
it("is useful for comparing arguments", function() {
var callback = jasmine.createSpy('callback'); callback('foobarbaz'); expect(callback).toHaveBeenCalledWith(jasmine.stringMatching('bar'));
expect(callback).not.toHaveBeenCalledWith(jasmine.stringMatching(/^bar$/));
});
});
});

自定义Matching

定义对象的asymmetricMatch方法就实现了自定义Matching

describe("custom asymmetry", function() {
var tester = {
asymmetricMatch: function(actual) {
var secondValue = actual.split(',')[1];
return secondValue === 'bar';
}
}; it("dives in deep", function() {
expect("foo,bar,baz,quux").toEqual(tester);
}); describe("when used with a spy", function() {
it("is useful for comparing arguments", function() {
var callback = jasmine.createSpy('callback'); callback('foo,bar,baz'); expect(callback).toHaveBeenCalledWith(tester);
});
});
});

时间测试

Jasmine Clock可用于测试随时间变化的代码。

在使用前需要调用jasmine.clock().install(),时间从install开始进行;在使用完成后,务必调用jasmine.clock().uninstall(),这样才能再次install,并且时间才会归0。

jasmine.clock().tick(milliseconds)函数可以让时间前进milliseconds毫秒。

当然了,可以直接使用jasmine.clock().mockDate(baseTime)将基础时间设置为baseTime

describe("Manually ticking the Jasmine Clock", function() {
var timerCallback; beforeEach(function() {
timerCallback = jasmine.createSpy("timerCallback");
jasmine.clock().install();
}); afterEach(function() {
jasmine.clock().uninstall();
}); it("causes a timeout to be called synchronously", function() {
setTimeout(function() {
timerCallback();
}, 100); expect(timerCallback).not.toHaveBeenCalled(); jasmine.clock().tick(101); expect(timerCallback).toHaveBeenCalled();
}); it("causes an interval to be called synchronously", function() {
setInterval(function() {
timerCallback();
}, 100); expect(timerCallback).not.toHaveBeenCalled(); jasmine.clock().tick(101);
expect(timerCallback.calls.count()).toEqual(1); jasmine.clock().tick(50);
expect(timerCallback.calls.count()).toEqual(1); jasmine.clock().tick(50);
expect(timerCallback.calls.count()).toEqual(2);
}); describe("Mocking the Date object", function() {
it("mocks the Date object and sets it to a given time", function() {
var baseTime = new Date(2013, 9, 23);¶
If you do not provide a base time to mockDate it will use the current date. jasmine.clock().mockDate(baseTime); jasmine.clock().tick(50);
expect(new Date().getTime()).toEqual(baseTime.getTime() + 50);
});
});
});

异步支持

Jasmine还支持异步测试,调用beforeAll, afterAll, beforeEach, afterEach, 和 it的函数参数时都有个可选参数done ,声明了这个参数后只有调用done后才会继续以后的代码,所有没有异步操作的时候不要手贱加上去。

异步操作的超时时间默认时5秒,只要5秒内没有done都会报错,可以给beforeAll, afterAll, beforeEach, afterEach, 和 it传递一个毫秒作为超时时间。也可以在所有describe外设置全局的jasmine.DEFAULT_TIMEOUT_INTERVAL

describe("Asynchronous specs", function() {
var value; beforeEach(function(done) {
setTimeout(function() {
value = 0;
done();
}, 1);
}); it("should support async execution of test preparation and expectations", function(done) {
value++;
expect(value).toBeGreaterThan(0);
done();
}); describe("long asynchronous specs", function() {
beforeEach(function(done) {
done();
}, 1000); it("takes a long time", function(done) {
setTimeout(function() {
done();
}, 9000);
}, 10000); afterEach(function(done) {
done();
}, 1000);
}); describe("A spec using done.fail", function() {
var foo = function(x, callBack1, callBack2) {
if (x) {
setTimeout(callBack1, 0);
} else {
setTimeout(callBack2, 0);
}
}; it("should not call the second callBack", function(done) {
foo(true,
done,
function() {
done.fail("Second callback has been called");
}
);
});
});
});