在控制器jasmine中测试.success和.error服务

时间:2016-09-22 05:37:06

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

我在控制器中调用了服务的功能。以下是代码

服务

(function () {
'use strict';
angular.module('MyApp')
    .service('MyService', ['$http', function ($http) {                                                  
        return {
            getMyData: function (extension) {                                        
                return $http.get('www.something.com');
            }                
        };
    }])
})();

控制器

var getMyData = function () {
            MyService.getMyData(extension).success(function (results) {
                //Some functionality here
            })
                .error(function (err, status) {
                //Some functionality here
            });
        }
$scope.Call=function(){
    getMyData();
}
$scope.Call();

现在请告诉我如何模拟服务电话(可能与提供商有关)。如何使用完整的代码覆盖率测试上述功能。

我的规范文件:

$provide.service("MyService", function () {
            this.getMyData= function () {
                var result = {
                    success: function (callback) {
                        return callback({ ServerFileName: "myserverfilename"});
                    },
                    error: function (callback) {
                        return callback({ ServerFileName: "myserverfilename" });
                    }
                };
                return result;
}           

//......
my controller initiation and other code

此代码未涵盖错误阻止并提供错误

Cannot read property 'error' of undefined

请帮助我如何在我的spec文件中编写/模拟我的服务的getMyData函数

提前致谢。

3 个答案:

答案 0 :(得分:2)

由于.success.error已经过时且已被.then(successCallback, errorCallback)替换,您应该考虑通过一次调用替换已绑定的.success.error来电到.then方法,有两个回调作为参数:第一个是成功回调,第二个是错误回调。

如果这是你愿意做的,这是你的工作实例:

模块,服务和控制器

angular.module('MyApp', []);

angular.module('MyApp')
.service('MyService', ['$http', function ($http) {                                                  
    return {
        getMyData: function (extension) {                                        
            return $http.get('www.something.com');
        }                
    };
}]);

angular.module('MyApp')
.controller('MyAppController', ['$scope', function($scope){
    var extension = { foo: 'bar' };
    var getMyData = function () {
        MyService.getMyData(extension).then(function (results) {
            //Some functionality here
        }, function (err, status) {
            //Some functionality here
        });
    }
    $scope.Call=function(){
        getMyData();
    }
    $scope.Call();
}]);

您的测试

describe('Controller: MyAppController', function(){
    beforeEach(module('MyApp'));
    var flag, extension, $q;
    extension = { foo: "bar" };
    beforeEach(inject(function($controller, $rootScope, _MyService_, _$q_) {
        $scope = $rootScope.$new();
        MyService = _MyService_;
        $q = _$q_;
        spyOn(MyService, 'getMyData').and.callFake(function(){
            return flag ? $q.when(): $q.reject();
        });
        MyAppController = $controller('MyAppController', {
            $scope: $scope,
            MyService: MyService
        });
    }));

    describe('function: Call', function() {
        //Text for Success Callback
        it('should implicitly call MyService.getMyData with an extension object', function() {
            flag = true;
            $scope.Call();
            expect(MyService.getMyData).toHaveBeenCalledWith(extension);
        });
        //Text for Error Callback
        it('should implicitly call MyService.getMyData with an extension object', function() {
            flag = false;
            $scope.Call();
            expect(MyService.getMyData).toHaveBeenCalledWith(extension);
        });
    });
});

<强>更新 我尝试过这样的东西,但没有运气。由于.error()的调用被链接到.success()调用,并且只有在调用.success()后才会调用它,它将永远不会到达.error()打电话,我们将无法模仿.error()。因此,如果我们尝试这样做,我们总会得到如下错误:

  

无法读取未定义

的属性'错误'

因此,您可以使用评论/*istanbul ignore next*/跳过此部分,或切换为.then()

希望这有帮助。

答案 1 :(得分:0)

您需要使用spyon,它会为您的服务创建某种模拟。您需要在测试文件中执行此操作。请检查以下代码:

spyOn(MyService, "getMyData").and.callFake(() => {
            return {
                error: (callback) => {
                    return callback({});
                }
            };
        });

希望我回答你的问题

答案 2 :(得分:0)

这是解决方案。我也遇到过类似的问题。看来我们必须设计自己的代码,而 Jasmine 允许我们设计,自定义回调方法在链接中,返回对象是Javascript方法链接的任务。使用我的解决方案,您不要需要使用然后功能

$provide.service("MyService", function () {
            this.getMyData= function () {
                var result = {
                    success: function (callback) {
                        callback({ ServerFileName: "myserverfilename"});
                        //returning main object for error callback invoke to occur
                        return this;

                    },
                    error: function (callback) {
                        callback({ ServerFileName: "myserverfilename" });
                        //returning this object will initialize error callback with object since you are chaining
                        return this;
                    }
                };
                return result;
}