【问题标题】:Angular unit testing promisesAngular 单元测试承诺
【发布时间】:2016-05-01 20:12:58
【问题描述】:

我对 Promise 不熟悉,并且似乎可以运行实际代码,但也尝试编写单元测试...

这是我的控制器:

appModule.controller('MyController', function($scope, myService, $timeout, mySecondService) {

    $scope.accept = false;
    $scope.loading = false;
    $scope.text = 'Some text';

    $scope.testCall = function() {

        $scope.person = true;
        $scope.text = '';
        $scope.loading = true;

        myService.getWeather()            
            .then(function(data) {
                if (data.valid===true) {
                    $timeout(function(){
                        $scope.loading = false;
                        $scope.accept = true;

                        $timeout(function(){
                            $scope.customer.cart = false;
                        }, 1400);

                    }, 1500);
                }
                else {
                    $scope.person = false;
                    $scope.newMessage = mySecondService.getItem();
                }
            }, function(error) {
                $scope.person = false;
                $scope.newMessage = mySecondService.getItem();
            });
    }
});

控制器规格:

beforeEach(module('myApp'));

describe("MyController Tests", function() {

    var scope;
    var ctrl;

    var customerInfo = {           
            "ID" : "212143513",
            "firstName" : "Lewis",
            "lastName" : "Noel"
    };

    beforeEach(inject(function($rootScope, $controller, myService) {
        scope = $rootScope.$new();
        rootScope = $rootScope;        

        mockMyService = myService;      

        ctrl = $controller('MyController', {$scope:scope, myService:mockMyService});

        spyOn(scope, 'testCall').and.callThrough();
    }));

    it("On controller load, initialise variables", function() {
        expect(scope.text).toEqual('Some text');
        expect(scope.loading).toEqual(false);
        expect(scope.accept).toEqual(false);
    });
});

以上测试了 $scope 的初始化,但服务中没有任何内容...

这是我的服务:

appModule.factory('myService', function ($http, $q) {
return {
        getWeather: function() {
            return $http.get('/cart/customerCart/546546')
                .then(function(response) {
                    if (typeof response.data === 'object') {
                        return response.data;
                    }
                    else {
                        // invalid response
                        return $q.reject(response.data);
                    }

                }, function(response) {
                    // something went wrong
                    return $q.reject(response.data);
                });
        }
    };
});

【问题讨论】:

  • 您需要隔离您正在测试的组件。如果您在控制器测试中而不是将原始服务分配给控制器,请传递一个模仿您服务的相同 API 但不发出任何请求的对象。或者使用 ngMockE2E 服务。无论如何,您需要手动调用 scope.$apply 来运行请求,因为模拟模块正在持有然后被执行
  • @Raulucco - 不是一个非常有用的评论。如果您查看我的第一个测试,您可以看到我隔离了控制器。一旦成功,接下来我将隔离服务。

标签: angularjs unit-testing jasmine karma-jasmine angular-services


【解决方案1】:

如果您询问如何测试服务,我会这样做:

describe("myService", function() {
  var myService;
  beforeEach(inject(function($rootScope, _myService_) {
    myService = _myService_;
  }));

  it("On controller load, initialise variables", function() {
    var result;
    myService.getWeather().then( function (data) {
      result = data;
    });
    $rootScope.$apply();
    expect(result).toEqual(whatever);
  });
});

注意事项:

  • 您可以使用 _myService_ 下划线技巧来获取服务 myService,而无需创建具有该名称 (see docs) 的局部变量。
  • 您需要调用 $rootScope.$apply() 来刷新测试中的承诺。 see docs

编辑: 你错误地使用了承诺,我会重构你的工厂(未经测试):

appModule.factory('myService', function ($http, $q) {
  return {
    getWeather: function() {
      var defer = $q.defer();
      $http.get('/cart/customerCart/546546')
         .then(function(response) {
            if (typeof response.data === 'object') {
               defer.resolve(response.data);
            }
            else {
               // invalid response
               defer.reject(response.data);
            }
          }, function(response) {
            // something went wrong
            defer.reject(response.data);
          });
      return defer.promise;
    }
  };
});

【讨论】:

  • 谢谢。这是对我的场景的有效测试吗?这是否测试 $q ??
  • 是的,就是这个想法(尽管请注意我只是在答案中输入了该代码,所以请检查)。如果没有,请回来询问。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-19
  • 1970-01-01
  • 2017-08-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多