在控制器 jasmine 中测试服务的 .success 和 .error [英] testing .success and .error of service in controller jasmine

查看:24
本文介绍了在控制器 jasmine 中测试服务的 .success 和 .error的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在控制器中调用了服务的函数.下面是代码

I have a call to service's function in a controller. Below is the code

服务

(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();

现在请告诉我如何模拟服务调用(可能与提供者有关).如何在代码覆盖率完整的情况下测试上述功能.

Now please tell me how to mock the service call (may be with providers). How to test the above functions with complete code coverage.

我的规范文件:

$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

这段代码没有覆盖错误块并给出错误

This code is not covering error block and giving the error

Cannot read property 'error' of undefined

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

Please help me how to write/mock the getMyData function of my service in my spec file

提前致谢.

推荐答案

由于 .success.error 是旧的并且已被替换为 .then(successCallback, errorCallback),您应该考虑用对 .then 的单个调用替换链接的 .success.error 调用有两个回调作为参数的方法:第一个是成功回调,第二个是错误回调.

Since .success and .error are old and have been replaced with .then(successCallback, errorCallback), you should consider replacing your chained .success and .error calls with a single call to the .then method with two callbacks as arguments to it: first being a success callback and second being an error callback.

如果这就是您愿意做的,这里是您的工作示例:

If that's what you're willing to do, here's your working example:

模块、服务和控制器

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() 之后才会调用它code> 已被调用,它将永远不会到达 .error() 的调用,我们将无法模拟 .error().所以如果我们尝试这样做,我们总是会得到这样的错误:

UPDATE: I've tried making something like this to work but with no luck. Since .error()'s call is chained to .success() call, and that is something that will get called only after .success() has been called, it will never get to .error()'s call and we'll not be able to mock .error(). So if we try doing that, we'll always get an error like:

无法读取未定义的属性错误"

Cannot read property 'error' of undefined

因此,您可以使用注释 /*istanbul ignore next*/ 跳过覆盖范围中的这一部分,或者切换到 .then().

So either you can use the comment /*istanbul ignore next*/ to skip this part in the coverage, or switch to .then().

希望这会有所帮助.

这篇关于在控制器 jasmine 中测试服务的 .success 和 .error的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆