简体   繁体   English

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

[英]Unit test inject dependency like controller for service in angularJS

Lets see, we have this according to: https://docs.angularjs.org/guide/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');
    });
  });
});

now i am making service and factory, is there any equivalent to ____$controller____ for service and factory? 现在我正在服务和工厂,是否有相当于____ $ controller____的服务和工厂? so i can inject it with something else like: 所以我可以用其他东西注入它:

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

and change the inner functions of the dependency so i can test it, or is there any better approach? 并改变依赖的内部函数,以便我可以测试它,或者有更好的方法吗?

Edit: to make question more clear here is the example of the question: 编辑:为了使问题更清楚,这里是问题的例子:

i have this: 我有这个:

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

how do i use the equivalent of 我该如何使用相当于

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

so i can inject $scope and $http with something else to myService? 所以我可以向myService注入$ scope和$ http与其他东西?

You can't inject dependencies to factories or services on the go, but you can mock the dependencies with your custom objects and have angular substitute them automatically. 您无法随时随地将依赖项注入工厂或服务,但您可以使用自定义对象mock依赖项,并使用角度自动替换它们。 You can use $provide for that. 您可以使用$provide Here is an example: 这是一个例子:

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

});

When testing: 测试时:

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

   });
}));

After doing a workarround, i found out from https://www.sitepoint.com/unit-testing-angularjs-services-controllers-providers/ about the service. 做完工作之后,我从https://www.sitepoint.com/unit-testing-angularjs-services-controllers-providers/了解了该服务。 i tested out the tutorial here and here is the test script: 我在这里测试了教程,这里是测试脚本:

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

and i try my own test script: 我尝试自己的测试脚本:

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

        });
    });
})();

apparently in somewhere in my code, there is an app.run which inside do the 显然在我的代码中的某个地方,有一个app.run里面做的

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

and causes the error the moment i inject the $http with something else because headers not defined, i thought it was from my own test script because they are using same name, but apparently this is the one causing problem. 并且因为我没有定义头文件而我注入$ http的那一刻导致错误,我认为它来自我自己的测试脚本,因为他们使用相同的名称,但显然这是引起问题的那个。

So, actually the moment we load in testing mode, the angularjs still do the whole running of application, in which i forgot about this one. 所以,实际上在我们加载测试模式的那一刻,angularjs仍然执行应用程序的整个运行,我忘了这个。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM