Angularjs模拟一个返回$ http承诺的函数

时间:2015-12-17 19:25:20

标签: javascript angularjs jasmine angular-mock

我有和angularjs应用程序,其中我有一个控制器调用返回$ http调用的服务。该应用程序工作正常,但我正在尝试测试控制器并遇到问题。

我的服务:

myApp.factory("MyService", function ($http) {
     var service = {};

     service.save = function (item) {
         return $http.post('../api/Save', item)
             .success(function () {
                 console.log("Saved items on current page");
             })
             .error(function () {
                 console.log("Error saving items on page")
             });
         };
      return service;
});

我的控制器:

myApp.controller("MyCtrl", function ($scope, MyService) {
    $scope.save = function () {
       MyService.save($scope.data)
        .success(function () {
            //do something
        }).error(function () {
            //do something else
        });
    };        
});

该应用程序完全按预期工作。

我的spec文件:

describe('MyCtrl', function () {
    var myCtrl, mySvc, scope;

    beforeEach(function () {
        module('MyApp');
        module(function ($provide) {
            $provide.service('MyService', function () {
                this.save = function () { };
            });
        });
        inject(function ($injector) {
            mySvc = $injector.get('MyService');
        });
        spyOn(mySvc, 'save').and.callFake(function () {
            return {
                success: function (callback) {
                    callback({ /* something */ });
                },
                error: function (callback) { 
                    callback({/* something else */ }); 
                }
            };
        });
        inject(function ($controller, $rootScope) {
            scope = $rootScope.$new();
            myCtrl = $controller('MyCtrl', { $scope: scope });
        });
    });
    describe('when save button has been hit', function () {
        it('should save', function () {
            scope.save();
            expect(mySvc.save).toHaveBeenCalled();
        });
    });
});

测试给我一个错误'undefined' is not an object (near '...}).error(function () {...')。如果我从控制器本身删除'...}).error(function () {...')部分,那么测试工作正常,但我不想摆脱该功能。

2 个答案:

答案 0 :(得分:0)

尝试使用return callback()

   spyOn(mySvc, 'save').and.callFake(function () {
        return {
            success: function (callback) {
                return callback({ /* something */ });
            },
            error: function (callback) { 
                return callback({/* something else */ }); 
            }
        };
    });

答案 1 :(得分:0)

我得到了一些工作!问题是在我的控制器中我正在链接响应行为,模拟的函数不知道如何处理。我找到的解决方案是在每个案例后直接返回函数。

 $provide.service('MyService', function () {
       this.save = function () {
            return {
                 success: function (callback) {
                    callback();
                    return this;
                 }, 
                 error: function (callback) {
                    callback();
                    return this;
                 },
                 finally: function (callback) {
                    callback();
                    return this;
                 }
            };
       };
  });

然后将间谍改为:

spyOn(mySvc, 'save').and.callThrough();