【问题标题】:Angular Jasmine test function call inside then然后在里面调用Angular Jasmine测试函数
【发布时间】:2016-02-10 17:57:25
【问题描述】:

这是我要测试的控制器功能。

  saveItem = (): void => {
    this.updateItem();
    this.loadingDialogService.showIndicator("Saving Item");        
this._editItemService.updateItem(this.item).then((updatedItem: Item) => {
            this.loadingDialogService.cancelDialog();
            this.goToMainView();
        }).catch(() => {
            this.loadingDialogService.showErrorDialog("Failed to Save Item");
            //this._log.error("Error CallingItemService");
        });
    }

这是我的测试:

it("should call method saveItem", () => {
            spyOn(controller, 'updateItem');
            spyOn(loadingDialogService, 'showIndicator');
            spyOn(editItemService, 'updateItem').and.callFake(() => {
                let result: Item
                deferred.resolve(result);  
                return deferred.promise;              
            });
            spyOn(loadingDialogService, 'cancelDialog');
            spyOn(controller, 'goToMainView');
            controller.saveItem();
            expect(controller.updateItem).toHaveBeenCalled();
            expect(loadingDialogService.showIndicator).toHaveBeenCalled();
            expect(_editItemService.updateItem).toHaveBeenCalled();
            expect(loadingDialogService.cancelDialog).toHaveBeenCalled();
            expect(controller.goToMainView).toHaveBeenCalled();
        });

测试在最后两个期望时失败,抛出错误提示

预期的间谍 cancelDialog 已被调用。

预计间谍 goToMainView 已被调用。

我猜测试没有执行 then 函数中的函数。有人能指出错误在哪里吗?

【问题讨论】:

    标签: angularjs jasmine


    【解决方案1】:

    您有一个要解决的承诺,因此您需要在函数调用之后但在测试之前运行一个摘要循环。

    it("should call method saveItem", () => {
            spyOn(controller, 'updateItem');
            spyOn(loadingDialogService, 'showIndicator');
            spyOn(editItemService, 'updateItem').and.callFake(() => {
                let result: Item
                deferred.resolve(result);  
                return deferred.promise;              
            });
            spyOn(loadingDialogService, 'cancelDialog');
            spyOn(controller, 'goToMainView');
            controller.saveItem();
            $scope.$digest();
            expect(controller.updateItem).toHaveBeenCalled();
            expect(loadingDialogService.showIndicator).toHaveBeenCalled();
            expect(_editItemService.updateItem).toHaveBeenCalled();
            expect(loadingDialogService.cancelDialog).toHaveBeenCalled();
            expect(controller.goToMainView).toHaveBeenCalled();
        });
    

    话虽如此,您的测试稍后会导致您遇到问题,因为它有 5 个断言 (expect()s)。当一个失败时,您将不得不浪费时间弄清楚它是哪一个。坚持每个测试一个断言(OAPT)。这应该是 5 个测试,每个测试一个断言。这样,当某件事情发生故障时,您就知道它是什么。

    【讨论】:

    • 谢谢!示波器上的 $digest() / $apply() 是我所缺少的。现在完全可以理解为什么它不起作用了。
    【解决方案2】:

    解决方案

    fakeAsync 内运行测试并在expect 之前运行tick()

    服务:

    getFirebaseDoc() {   
      this.db.firestore.doc('some-doc').get()
        .then(this.getFirebaseDocThen)
        .catch(this.getFirebaseDocCatch);
    }
    

    单元测试:

    it('should call getFirebaseDocThen', fakeAsync(() => {            // note `fakeAsync`
        spyOn(service, 'getFirebaseDocThen');
        spyOn(service.db.firestore, 'doc').and.returnValue({
          get: (): any => {
            return new Promise((resolve: any, reject: any): any => {
              return resolve({ exists: true });
            });
          },
        });
        service.getFirebaseDoc();
        tick();                                                       // note `tick()`
        expect(service.getFirebaseDocThen).toHaveBeenCalled();
    }));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-13
      • 1970-01-01
      • 1970-01-01
      • 2012-06-26
      • 2019-05-02
      • 1970-01-01
      相关资源
      最近更新 更多