单元测试注入依赖性,如angularJS中的服务控制器

时间:2016-10-25 08:06:03

标签: javascript angularjs unit-testing

让我们看看,我们有根据:https://docs.angularjs.org/guide/unit-testing

describe('PasswordController', function() {
  beforeEach(module('app'));

  var $controller;

  beforeEach(inject(function(_$controller_){
    // The injector unwraps the underscores (_) from around the parameter names when matching
    $controller = _$controller_;
  }));

  describe('$scope.grade', function() {
    it('sets the strength to "strong" if the password length is >8 chars', function() {
      var $scope = {};
      var controller = $controller('PasswordController', { $scope: $scope });
      $scope.password = 'longerthaneightchars';
      $scope.grade();
      expect($scope.strength).toEqual('strong');
    });
  });
});

现在我正在服务和工厂,是否有相当于____ $ controller____的服务和工厂?所以我可以用其他东西注入它:

var controller = $controller('PasswordController', { $scope: $scope });

并更改依赖项的内部函数,以便我可以测试它,还是有更好的方法?

修改以使问题更清晰 这是问题的例子:

我有这个:

var app = angular.module("app").service("MyService",["$scope","$http",function($scope,$http){
    this.myFunction = function(){
        $http.get("/myApi/1");
    }
}]);

我如何使用等效的

var controller = $controller('PasswordController', { $scope: $scope });

所以我可以向myService注入$ scope和$ http吗?

2 个答案:

答案 0 :(得分:2)

您无法随时随地将依赖项注入工厂或服务,但您可以mock自定义对象的依赖项,并自动替换它们。您可以使用$provide。这是一个例子:

angular.module('app').service('some', function(dependencyService) {

});

测试时:

beforeEach(module(function($provide) {
   $provide.value('dependencyService', {

   });
}));

答案 1 :(得分:1)

在做完工作之后,我从https://www.sitepoint.com/unit-testing-angularjs-services-controllers-providers/找到了有关该服务的信息。我在这里测试了教程,这里是测试脚本:

(function () {
    angular.module('services', [])
        .service('sampleSvc', ['$window', 'modalSvc', function ($window, modalSvc) {
            this.showDialog = function (message, title) {
                if (title) {
                    modalSvc.showModalDialog({
                        title: title,
                        message: message
                    });
                } else {
                    $window.alert(message);
                }
            };
      }]);
    describe("Testing service", function () {
        var mockWindow, mockModalSvc, sampleSvcObj;
        beforeEach(module(function ($provide) {
                $provide.service('$window', function () {
                    this.alert = jasmine.createSpy('alert');
                });
                $provide.service('modalSvc', function () {
                    this.showModalDialog = jasmine.createSpy('showModalDialog');
                });
            }, 'services'));

        beforeEach(inject(function ($window, modalSvc, sampleSvc) {
            mockWindow = $window;
            mockModalSvc = modalSvc;
            sampleSvcObj = sampleSvc;
        }));
        it('should show alert when title is not passed into showDialog', function () {
            var message = "Some message";
            sampleSvcObj.showDialog(message);

            expect(mockWindow.alert).toHaveBeenCalledWith(message);
            expect(mockModalSvc.showModalDialog).not.toHaveBeenCalled();
        });

        it('should show modal when title is passed into showDialog', function () {
            var message = "Some message";
            var title = "Some title";
            sampleSvcObj.showDialog(message, title);

            expect(mockModalSvc.showModalDialog).toHaveBeenCalledWith({
                message: message,
                title: title
            });
            expect(mockWindow.alert).not.toHaveBeenCalled();
        });
    });
})();

我尝试自己的测试脚本:

(function () {
    describe("Testing service", function () {
        var mockHttp, mockCookies, mockApi;
        beforeEach(function () {
            module(function ($provide) {
                $provide.service('$http', function () {
                    this.defaults = {
                        headers: {
                            common: {

                            }
                        }
                    };
                });
                $provide.service('$cookies', function () {

                });
            });
            module('timesheet');
        });

        beforeEach(inject(function ($http, $cookies, APIService) {
            mockHttp = $http;
            mockCookies = $cookies;
            mockApi = APIService;
        }));
        it('Test Service', function () {

        });
    });
})();

显然在我的代码中的某个地方,有一个app.run,里面有

$http.defaults.headers.common.Authorization = 'Bearer ' + $cookies.get('sessionToken');

并在我用其他东西注入$ http时导致错误,因为标头未定义,我认为它来自我自己的测试脚本,因为它们使用相同的名称,但显然这是导致问题的那个。

所以,实际上在我们加载测试模式的那一刻,angularjs仍然执行应用程序的整个运行,我忘了这个。