在Jasmine中测试异步代码

时间:2018-04-05 19:19:14

标签: javascript jasmine karma-jasmine

我正在使用Jasmine编写一些测试用例。它看起来像这样:

班级定义:

class Person {
  constructor(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  }

  getFullName() {
    return this.firstName + this.lastName;
  }

  getName () {
    setTimeout(() => {
      return this.getFullName();
    }, 100)
  }
}

module.exports = Person;

测试代码:

 const Person = require('./index');

 describe('Test Person methods', () => {
  beforeEach(() => {
    programmer = new Person('John', 'Gray');
    spyOn(programmer, 'getFullName');
    programmer.getName();
  });

  it('getName should call getFullName', () => {
    expect(programmer.getFullName).toHaveBeenCalled();
  })
});

getName是一个异步函数,在一段时间后会调用getFullName。由于这种异步性质,it规范在调用getName后立即执行,因此测试失败。

我知道我可以使用Jasmine的done函数来执行异步测试,但我不知道如何在这里实现它?在文档中,done方法仅在异步代码中调用,但测试无法访问该代码,因为它由getName方法在内部处理。

或者有没有其他方法不使用done方法?

Here是此代码的工作示例。

2 个答案:

答案 0 :(得分:0)

我认为你需要将done参数传递给函数并调用它:

beforeEach((done) => {
    someObj = new SomeClass();
    spyOn(someObj, 'onSuccess');
    someObj.start();
    done();
});

it('start should call onSuccess', (done) => {
    expect(someObj.onSuccess).toHaveBeenCalled();
    done();
});

来源:Jasmine Documentation

答案 1 :(得分:0)

您对getName的实施是错误的。在javascript中,要处理异步函数的结果,您需要将callback传递给异步函数或返回Promise。一旦修复了实现,那么测试它应该很简单:

使用回调方法:

getName (callback) {
    setTimeout(() => {
        callback(this.getFullName());
    }, 100)
}

beforeEach(done => {
    ...
    programmer.getName(name => { 
      done(); // at this point the async func. has completed
    });
});

使用承诺:

getName () {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve(this.getFullName());
        }, 100)
    }) 
}

beforeEach(done => {
    ...
    programmer
        .getName()
        .then(name => {
            done(); // at this point the async func. has completed
        });
});

修改

如果你正在使用Promise,你也可以使用async / await(Jasmine> = 2.7):

beforeEach(async () => {
    ...
    const name = await programmer.getName();
    // async func has completed here. 
    // await acts like .then() and "waits" for your promise to resolve
    // done wouldn't be needed because there aren't any callbacks
});