Подтвердить что ты не робот

Сделайте модуль доступным в контроллере, который тестируется жасмином через Resharper

Я могу успешно протестировать контроллер, используя жасмин через PhantomJs, используя Resharper 9.2. как испытатель.

Я выполнил инструкции https://blogs.endjin.com/2014/09/unit-testing-angularjs-with-visual-studio-resharper-and-teamcity/ для настройки Resharper.

Это сработало: я могу запустить тест для контроллера, если я не буду определять модули, от которых он зависит:

Контроллер:

    var moduleName;
(function (moduleName) {
    'use strict';
    var testableController = (function () {
        function testableController($scope) {
            var _this = this;
            this.$scope = $scope;

            $scope.title = "Welcome";
        }
        testableController.className = 'testableController';
        return testableController;
    }());
    moduleName.testableController = testableController;
})(moduleName || (moduleName = {}));

Файл спецификации выглядит следующим образом:

    ///<reference path="~/Scripts/jasmine/jasmine.js"/>
///<reference path="~/Scripts/jasmine/angular.js"/>
///<reference path="~/Scripts/jasmine/angular-mocks.js"/>
///<reference path="~/Scripts/angular-ui/ui-bootstrap.min.js" />
///<reference path="~/Scripts/jasmine/controllers.js"/>
///<reference path="~/Scripts/App/Controllers/testableController.js" />
///<reference path="~/Scripts/App/AppJasmine.js" />
describe("Controllers", function() {

    beforeEach(module("moduleName"));

    describe("Jasmine  testableController", function () {

        var scope,
            controller;

        beforeEach(inject(function ($rootScope, $controller) {
            scope = $rootScope.$new();
            controller = $controller('testableController', { $scope: scope });
        }));

        it('should set the page title as "Welcome"', function () {
            expect(scope.title).toBe('Welcome');
        });

    });
});

Реальный контроллер использует angular ui bootstrap "ui.bootstrap". контроллер работает на странице, если я изменяю его на следующий образец, но когда я пытаюсь его протестировать, появляется ошибка

Error: [$injector:unpr] Unknown provider: $templateRequestProvider <- $templateRequest <- $uibModal
http://errors.angularjs.org/1.2.24/$injector/unpr?p0=%24templateRequestProvider%20%3C-%20%24templateRequest%20%3C-%20%24uibModal in http://localhost:61032/referenceFile?path=~/webui/trunk/Netvacation.Pegasus.WebUI/Scripts/jasmine/angular.js (line 3802)

Контроллер с зависимостью от Bootstrap

angular.module('moduleName', ['ui.bootstrap']);
var moduleName;
(function (moduleName) {
    'use strict';
    var testableController = (function () {
        function testableController($scope, $uibModal) {
            var _this = this;
            this.$scope = $scope;
            this.$uibModal = $uibModal;
            $scope.title = "Welcome";
        }
        testableController.className = 'testableController';
        return testableController;
    }());
    moduleName.testableController = testableController;
})(moduleName || (moduleName = {}));

** РЕДАКТИРОВАТЬ 1 ** Я попробовал

beforeEach(
    function () {
        module("ui.bootstrap");
        module("moduleName");
    }
    );

но имеют одинаковую ошибку.

Изменить 2 Я использую

http://angular-ui.github.io/bootstrap/ Версия: 1.3.3 - 2016-05-22

AngularJS v1.2.24

Изменить 3 Я не хочу тестировать $uibModal, но издеваюсь над ним.

4b9b3361

Ответ 1

Я знаю две стратегии для издевки службы с несколькими вариантами синтаксиса, как и все в Angular... Вы можете просто добавить литерал объекта в объявление контроллера или создать собственные службы и добавить их в модуль используя $provider:

Если служба - это всего лишь оболочка некоторого уровня данных или API, вы можете издеваться над ее функциональностью с литеральным объектом и вводить, если это правильно в конструкторе контроллера, следуя синтаксису примера, это можно сделать следующим образом:

var currentAuth;

beforeEach(inject(function ($rootScope, $controller) {
    scope = $rootScope.$new();
    currentAuth = {uid: 1, name: juan, getFriends: function() { ... }};

    controller = $controller('TestableCtrl', {'$scope': $scope, 'currentAuth': currentAuth });
}));

В этом случае "currentAuth" - это служба, которая предоставляет текущему зарегистрированному пользователю в приложении.

Это допустимо только в том случае, если вам не нужно вводить какую-либо услугу в функции, определенные в объекте. Это было бы эквивалентно созданию службы стоимости и ее ввода в модуль. Если методам внутри издевающегося сервиса нужна какая-либо услуга, вам придется создать factory или службу, добавить эту службу в модуль и затем ввести ее как любую другую настраиваемую службу. См. Этот пример, который я использую для издевательства службы аутентификации с угловым огнем:

 var $controller, $rootScope, $scope, $location, Auth;

  beforeEach(function(){
    module('planner.login');

    module(function($provide){

      $provide.factory('Auth', function($q){
        return {
          $signInWithEmailAndPassword: function(email, pass) {
            return $q.reject({error: 'ERROR'});
          }
        };
      });

      return null;
    });

  });

  beforeEach(function(){

    inject(function($controller, $rootScope, _Auth_) {
      $scope = $rootScope.$new();
      Auth = _Auth_;

      $controller("TestableCtrl", {
        $scope: $scope,
        Auth: Auth,
        $stateParams: {}
      });
    });

  });

В этом примере я создаю новый factory, который использует службу $q для возврата обещания angular (это не требовало тестирования в Chrome, но PhantomJS не имеет спецификации Promise). Обратите внимание, что для этого вам нужно два beforeEach, один для добавления провайдера в модуль, а другой - для ввода провайдера в контроллер.

Какой из них использовать, зависит от того, что вы хотите проверить, и насколько глубоко вам нужно подражать оригинальному поведению службы. В вашем случае с uibmodal вам, вероятно, нужно вызвать ".open" в какой-то момент и шпион, который был вызван, но вам нужно только создать объект с этим свойством и шпионить за свойством объекта для этого. Поэтому первого подхода должно быть достаточно.

Итак, ваш код должен выглядеть примерно так:

describe("Controllers", function() {

    beforeEach(module("moduleName"));

    describe("Jasmine  testableController", function () {

        var scope,
            controller,
            uibModal;

        beforeEach(inject(function ($rootScope, $controller) {
            scope = $rootScope.$new();
            uibModal = { open: function() { return 'Whatever'; } }
            controller = $controller('testableController', { $scope: scope, $uibModal: uibModal });
        }));

        it('should set the page title as "Welcome"', function () {
            expect(scope.title).toBe('Welcome');
            // you will probably do something like this at some point to verify 
            // that the modal gets opened on click or following any other action:
            // var spy = spyOn(uibModal, 'open');
            // expect(spy).toHaveBeenCalled();
        });

    });
});

Я надеюсь, что это поможет, пожалуйста, скажите мне, если что-то неясно, я также изучаю тестирование приложений AngularJS и хотел бы знать, помогает ли это с помощью AngularUI.

Ответ 2

Первая проблема заключается в том, что вы не регистрируете контроллер в модуле. Поэтому он не знает о зависимостях модуля.

angular.module('modulename').controller('nameofthecontroller', controller);

И тогда вы можете высмеивать $uibModal, но не нужны; Он должен работать без этого макета;