【问题标题】:Angular - mocking out service method that returns a promiseAngular - 模拟返回承诺的服务方法
【发布时间】:2015-05-29 19:50:40
【问题描述】:

我正在尝试测试依赖于服务调用来获取一些数据的控制器方法。服务方法返回一个承诺,如果承诺被解决或拒绝,我想测试控制器的行为。

我想出了这种方法来改变我的模拟服务方法的行为,但它不起作用。当调用模拟的getData 方法时,getDataSuccess 标志始终为真。到目前为止,这是我所拥有的:

控制器:

app.controller('myController', function($scope, myService) {
       myService.getData()
         .then(function (data) {
             $scope.data = data;                   
         },
         function (data) {
             $scope.serverError = data;
         });
});

测试:

describe('myController', function () {

    var ctl, serviceMock, getDataSuccess, scope;

    beforeEach(function() {
            getDataSuccess = true;
            serviceMock = {};

        module('app', function ($provide) {
            $provide.value('myService', serviceMock);
        });      

        inject(function ($q) {
            serviceMock.getData = function () {                
                var defer = $q.defer();
                if (getDataSuccess) {
                    defer.resolve("theData");
                } else {
                    defer.reject("theData");
                }
                return defer.promise;
            };
        });
    });

    beforeEach(inject(function ($rootScope, $controller, $httpBackend, myService) {

        scope = $rootScope.$new();

        ctl = $controller('myController', {
            $scope: scope,          
            myService: myService,
        });        
    }));

    describe('myController loading data', function () {

        it('should set $scope.data if data load succeeds', function () {
            getDataSuccess = true;
            scope.$apply();
            expect(scope.data).toEqual("theData");
        });

        it('should set $scope.serverError if data load fails', function () {
            getDataSuccess = false;
            scope.$apply();
            expect(scope.serverError).toEqual("theData");
        });

    });

});

显然我在这里遗漏了一些东西。执行顺序不是我所期望的。做这种事情的正确方法是什么?

这是 Plunker 中的示例:http://plnkr.co/edit/ODyslivLorjaLM4EqlEF?p=preview

【问题讨论】:

    标签: angularjs jasmine


    【解决方案1】:

    myService.getData 函数在 myController 被初始化的地方被调用。所以如果你想通过设置getDataSuccess来改变getData函数的行为,你需要在设置getDataSuccess true/false后初始化myController。

    我推荐的是这样的。

    在 appSpec.js 中

    describe('myController', function () {
    
        var ctl, serviceMock, getDataSuccess, scope;
    
        beforeEach(function() {
            getDataSuccess = true;
            serviceMock = {};
    
            module('app', function ($provide) {
                $provide.value('myService', serviceMock);
            });      
    
            inject(function ($q) {
                serviceMock.getData = function () {                
                    var defer = $q.defer();
                    if (getDataSuccess) {
                        defer.resolve("theData");
                    } else {
                        defer.reject("theData");
                    }
                    return defer.promise;
                };
            });
        });
    
        beforeEach(inject(function ($rootScope, $controller, $httpBackend, myService) {
            scope = $rootScope.$new();
    //      
    //        ctl = $controller('myController', {
    //            $scope: scope,          
    //            myService: myService,
    //        });        
        }));
    
        describe('myController loading data', function () {
    
            it('should set $scope.data if data load succeeds', inject(function($controller, myService){
                getDataSuccess = true;
                ctl = $controller('myController', {
                    $scope: scope,          
                    myService: myService,
                });        
                scope.$apply();
                expect(scope.data).toEqual("theData");
            }));    
    
            it('should set $scope.serverError if data load fails', inject(function($controller, myService){
                getDataSuccess = false;
                ctl = $controller('myController', {
                    $scope: scope,          
                    myService: myService,
                });        
                scope.$apply();
                expect(scope.serverError).toEqual("theData");
            }));    
    
        });
    
    });
    

    This is updated plunker.

    【讨论】:

    • 是的,这就是问题所在。现在事后看来似乎很明显:)。谢谢!
    猜你喜欢
    • 2015-07-12
    • 1970-01-01
    • 1970-01-01
    • 2017-02-21
    • 1970-01-01
    • 2015-12-02
    • 1970-01-01
    • 2015-08-12
    • 2017-06-08
    相关资源
    最近更新 更多