无法读取未定义的AngularJS测试Promise的属性'.then'

时间:2019-10-10 09:05:52

标签: angularjs unit-testing jasmine karma-jasmine

我有以下AngularJS代码,正在尝试使用茉莉花广告业来测试:

(function() {
  "use strict";

  angular
    .module("beckon.steel.beckonstandard.directives.templateDetails", [
      // "beckon.steel.grid.services.beckonGridFactory",
      // "beckon.steel.connectorTemplate.services.connectorTemplateService",
      // "beckon.steel.dashboardTemplate.services.dashboardTemplateService",
      // "beckon.steel.scorecards.services.scorecardTemplateService",
      // "beckon.steel.channel.services.channelService",
      // "beckon.steel.beckonstandard.services.beckonStandardEntityEnum",
      // "beckon.steel.dimensions.dimensionService",
      // "beckon.steel.formulabuilder.services.formulaTemplateService",
    ])
    .directive("templateDetails", function(
      beckonStandardEntityEnum,
      connectorTemplateService,
      dashboardTemplateService,
      scorecardTemplateService,
      channelService,
      dimensionTemplateService,
      formulaTemplateService,
      $stateParams,
      svg,
      bnModalAlertService
    ) {
      return {
        templateUrl: "templateDetails",
        restrict: "E",
        scope: {
          entity: "@",
          baseState: "@",
        },
        controller: function($scope) {
          $scope.backArrow = svg.ARROW_LEFT;
          $scope.connector = null;
          $scope.dashboard = null;
          $scope.scorecard = null;

          $scope.icon = svg.ARROW_LEFT;

          const showAlert = function(successType, message) {
            bnModalAlertService.clearAlerts().setAlert({
              type: successType,
              msgSafeHtml: message,
            });
          };

          const onSuccess = () => showAlert("success", "Update successful");
          const onFail = (err) => {
            if (err.data && err.data.message) {
              showAlert("error", `Update unsuccessful: ${err.data.message}`);
              return;
            }
            showAlert("error", `Update unsuccessful:  ${err.statusText}`);
          };

          if ($scope.entity === beckonStandardEntityEnum.CONNECTOR.type) {
            $scope.backState = beckonStandardEntityEnum.CONNECTOR.uiRefState;

            connectorTemplateService
              .fetch($stateParams.id)
              .$promise.then(function(connector) {
                $scope.connector = connector;
              });

            $scope.updateConnector = function(connector) {
              connectorTemplateService
                .update($stateParams.id, connector)
                .$promise.then(onSuccess)
                .catch(onFail);
            };
          }

        },
      };
    });
})();

到目前为止,我已经嘲笑了大多数依赖关系,但是在嘲笑connectorTemplateService承诺时遇到了麻烦。

fdescribe("templateDetails", () => {
  "use strict";

  let $scope;
  let $compile;
  let $rootScope;

  let beckonStandardEntityEnum;
  let connectorTemplateService;
  let dashboardTemplateService;
  let scorecardTemplateService;
  let channelService;
  let dimensionTemplateService;
  let formulaTemplateService;
  let $stateParams;
  let svg;
  let bnModalAlertService;
  let $q;
  let resolvedValue;
  let deferred;

  const getIsolatedScope = (element) => element.isolateScope() || element.scope();

  beforeEach(module("beckon.steel.beckonstandard.directives.templateDetails"));
  beforeEach(
    module(($provide) => {
      svg = jasmine.createSpy();
      beckonStandardEntityEnum = {
        CONNECTOR: {
          type: "connectortype",
          uiRefState: "connectorUiRefState",
        },
        DASHBOARD: {
          type: "dashboardtype",
          uiRefState: "dashboardUiRefState",
        },
        SCORECARD: {
          type: "scorecardtype",
          uiRefState: "scorecardUiRefState",
        },
        CHANNEL: {
          type: "channeltype",
          uiRefState: "channelUiRefState",
        },
        DIMENSION: {
          type: "dimensiontype",
          uiRefState: "dimensionUiRefState",
        },
        FORMULA: {
          type: "formulatype",
          uiRefState: "formulaUiRefState",
        },
      };
      connectorTemplateService = {
        fetch: () => {},
        update: () => {},
      }

      bnModalAlertService = {
        clearAlerts: () => ({
          setAlert: jasmine.createSpy()
        }),
      };

      $stateParams = {
        id: "dummyid",
      };

      $provide.value("svg", svg);
      $provide.value("beckonStandardEntityEnum", beckonStandardEntityEnum);
      $provide.value("$stateParams", $stateParams);
      $provide.value("connectorTemplateService", connectorTemplateService);
      $provide.value("formulaTemplateService", formulaTemplateService);
      $provide.value("scorecardTemplateService", scorecardTemplateService);
      $provide.value("dimensionTemplateService", dimensionTemplateService);
      $provide.value("channelService", channelService);
      $provide.value("dashboardTemplateService", dashboardTemplateService);
      $provide.value("bnModalAlertService", bnModalAlertService);
    })
  );

  beforeEach(
    inject((_$rootScope_, _$compile_, _$q_) => {
      $compile = _$compile_;
      $rootScope = _$rootScope_;
      $scope = $rootScope.$new(true);
      $q = _$q_;


    })
  );

  describe("when entity matches CONNECTOR type", () => {
    it("initializes correctly", () => {
      // Arrange
      const element = angular.element(
        "<template-details entity='connectortype'>Here goes the template</template-details>"
      );

      spyOn(connectorTemplateService, "fetch").and.callFake((id) => {
        let deferred = $q.defer();
        deferred.resolve("the connector");
        return deferred.promise;
      });


      spyOn(connectorTemplateService, "update").and.callFake((id) => {
        let deferred = $q.defer();
        deferred.resolve("success");
        return deferred.promise;
      });

      // Act
      $compile(element)($scope);
      $scope.$digest();
      const isolatedScope = getIsolatedScope(element);
      isolatedScope.uiRefState = "connectorUiRefState";
      const expectedValue = "the connector";

      isolatedScope.updateConnector();
      isolatedScope.$apply();

      // Assertions

    });

  });
});

使用我模拟的方式(如在$ q角文档中所见),我收到错误cannot read property '.then' of undefined

我试图这样模拟

connectorTemplateService = {
  update: (id, connector) => ({
    $promise: {
      then: (fn) => {
        fn();
      },
    },
  }),
  fetch: (id) => ({
    $promise: {
      then: (fn) => {
        fn("the connector");
      },
    },
  }),
};

它适用于fetch方法,但不适用于update方法,因为它不是实际的承诺,并且update方法有一个catch块。谁能展示如何嘲笑这个诺言?

0 个答案:

没有答案