Jasmine基础语法

简介

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

转载于:https://www.cnblogs.com/bykp/p/6392322.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值