【问题标题】:Test if method was called by promise callback测试方法是否被 Promise 回调调用
【发布时间】:2019-12-03 23:03:05
【问题描述】:

我正在开发一个测试例程,用于检查调用特定方法时是否调用了某些方法。

我正在使用茉莉花。

当我测试第一级时它工作正常,但是如果我在第一级调用的回调函数中调用另一个方法,jasmine spyOn 不起作用。

一个小例子,如果我的代码:

onLogin(form: NgForm) {
  this.submitted = true;
  if (form.valid) {
    this.auth.login(this.login.username, this.login.password).then((value) => {
      if(value) {
        this.menu.enable(true, 'loggedInMenu');
        this.menu.enable(true, 'loggedOutMenu');
        this.navCtrl.setRoot(TabsPage);
      } else {
        let alert = this.alertCtrl.create({
          title: 'Ops',
          subTitle: 'Some things wrong.',
          buttons: ['OK']
        });
        alert.present();
      }
    });      
  }
}

// Test Routine
describe("onLogin", () => {
    it("makes expected calls when authentication successfully", () => {
        const menuControllerStub = fixture.debugElement.injector.get(MenuController);
        const authStub = fixture.debugElement.injector.get(Auth);
        const ngFormStub = fixture.debugElement.injector.get(NgForm);

        // it isn't works
        spyOn(menuControllerStub, "enable").and.callFake(() => {});

        // it's work fine
        spyOn(authStub, "login").and.callFake((username:string, password: string) => {
            return new Promise((callback, fallback) => {
                callback(true);
            });
        });

        comp.onLogin(ngFormStub);

        // failed
        expect(menuControllerStub.enable).toHaveBeenCalled();
        // success
        expect(autenticacaoStub.login).toHaveBeenCalled();
    });

只是为了测试,我将两行代码移到外部回调,测试工作正常。例如 :

onLogin(form: NgForm) {
  this.submitted = true;
  if (form.valid) {
      this.menu.enable(true, 'loggedInMenu');
      this.menu.enable(true, 'loggedOutMenu');

        this.auth.login(this.login.username, this.login.password).then((value) => {
        if(value) {
          this.navCtrl.setRoot(TabsPage);
        } else {
          let alert = this.alertCtrl.create({
            title: 'Ops',
            subTitle: 'Some thing wrong.',
            buttons: ['OK']
          });
          alert.present();
        }
    });      
  }
}

谁能帮帮我?

【问题讨论】:

    标签: angular typescript jasmine karma-jasmine


    【解决方案1】:

    这是因为您返回了一个 Promise,但它从未被解决或拒绝。尝试做

        spyOn(authStub, "login").and.callFake((username:string, password: string) => {
            return Promise.resolve(true);
        });
    

    编辑请试试这个:

    let spy = spyOn(menuControllerStub, 'enable').and.returnValue(false); 
    // ...
    expect(spy).toHaveBeenCalledTimes(2);
    

    【讨论】:

    • 它比我的代码简单,但仍然不起作用。我在登录回调中添加了一些 console.log,我看到两个示例(你的和我的)都调用了 this.menu.enable 方法。
    • 好的,如果你用spyOn(authStub, 'login').and.returnValue(Promise.resolve(true)); 转换你的间谍呢?
    • 相同的行为。我认为问题出在 spyOn(menuControllerStub, "enable") 无法检查该方法是否被调用。
    • 嗯,你从注入器中得到它,就像你为 auth 服务所做的那样,最后一个工作。根据您发布的内容,对我而言,问题是您从未真正进入您的then。你有代码覆盖率来支持它吗?看看它,看看你的then是否被它覆盖了
    • 我检查了 then 方法是否被调用了 console.log('call enable') 到 then 中。它被称为。
    【解决方案2】:

    Promise 是异步的,其余的测试在 promise 解决之前运行。

    在您的情况下,在 expect(menuControllerStub.enable).toHaveBeenCalled() 之前添加 tick() 方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-05-29
      • 1970-01-01
      • 2012-03-06
      • 1970-01-01
      • 1970-01-01
      • 2018-08-31
      • 1970-01-01
      相关资源
      最近更新 更多