Как мы можем протестировать методы углового контроллера без области видимости?

У нас есть несколько методов в Angular Controller, которые не находятся в переменной области видимости.

Кто-нибудь знает, как мы можем выполнить или вызвать эти методы внутри тестов Jasmine?

Вот основной код.

var testController = TestModule.controller('testController', function($scope, testService)
{

function handleSuccessOfAPI(data) {
    if (angular.isObject(data))
    {
       $scope.testData = data;
    }
}

function handleFailureOfAPI(status) {
    console.log("handleFailureOfAPIexecuted :: status :: "+status);
}

 // this is controller initialize function.
 function init() {
    $scope.testData = null; 

    // partial URL
    $scope.strPartialTestURL = "partials/testView.html;

    // send test http request 
    testService.getTestDataFromServer('testURI', handleSuccessOfAPI, handleFailureOfAPI);
}

 init();
}

Теперь в моем тесте жасмина мы передаем методы «handleSuccessOfAPI» и «handleFailureOfAPI», но они не определены.

Вот тестовый код жасмина.

describe('Unit Test :: Test Controller', function() {
var scope;
var testController;

var httpBackend;
var testService;


beforeEach( function() {
    module('test-angular-angular');

    inject(function($httpBackend, _testService_, $controller, $rootScope) {

        httpBackend = $httpBackend;
        testService= _testService_;

        scope = $rootScope.$new();
        testController= $controller('testController', { $scope: scope, testService: testService});
            });
});

afterEach(function() {
       httpBackend.verifyNoOutstandingExpectation();
       httpBackend.verifyNoOutstandingRequest();
    });

it('Test controller data', function (){ 
    var URL = 'test server url';

    // set up some data for the http call to return and test later.
    var returnData = { excited: true };

    // create expectation
    httpBackend.expectGET(URL ).respond(200, returnData);

    // make the call.
    testService.getTestDataFromServer(URL , handleSuccessOfAPI, handleFailureOfAPI);

    $scope.$apply(function() {
        $scope.runTest();
    });

    // flush the backend to "execute" the request to do the expectedGET assertion.
    httpBackend.flush();

    // check the result. 
    // (after Angular 1.2.5: be sure to use `toEqual` and not `toBe`
    // as the object will be a copy and not the same instance.)
    expect(scope.testData ).not.toBe(null);
});
});

person furqan kamani    schedule 07.04.2014    source источник


Ответы (2)


Как есть, у вас не будет доступа к этим функциям. Когда вы определяете именованную функцию JS, это то же самое, как если бы вы сказали

var handleSuccessOfAPI = function(){};

В этом случае было бы довольно ясно видеть, что переменная находится только в области видимости внутри блока и нет внешней ссылки на нее из контроллера упаковки.

Любая функция, которую можно вызвать дискретно (и, следовательно, протестировать), будет доступна в $scope контроллера.

person shaunhusain    schedule 07.04.2014
comment
Верный. Более того, мы не должны тестировать приватные функции. Как правило, init() подвергается модульному тестированию с фиктивными данными, которые гарантируют, что handleSuccessOfAPI или handleFailureOfAPI вызываются. Смоделированные объекты/данные должны управлять путем выполнения. - person dmahapatro; 07.04.2014
comment
Я вижу, что $scope делает функцию/переменную общедоступной (при сравнении с чем-то вроде Java). Я не слишком хорошо знаком с модульным тестированием в Java, но разве тестирование частных функций не является чем-то, что вы обычно делаете в Java? - person Chris; 11.04.2015
comment
Крис, у меня также ограниченный опыт написания тестов в целом, я написал несколько тестов JUnit, но я ни в коем случае не эксперт в тестировании или чем-то еще. Я предполагаю, что, поскольку частные функции не отображаются, когда вы создаете экземпляр объекта, вы все еще находитесь под тем же ограничением, что вы можете тестировать только те вещи, которые общедоступны. Я думаю, что в конечном итоге это имеет смысл, поскольку вы действительно заинтересованы в том, чтобы кусок кода выполнял задачу в стиле черного ящика, когда вы пишете тест, то есть если я указываю x, я ожидаю y, но детали реализации не беспокойство. - person shaunhusain; 12.04.2015
comment
@shaunhusain, так что, согласно этому ответу, именованные функции, которые не входят в область действия, не могут быть протестированы с помощью jasmine? - person Alok Mishra; 23.05.2016
comment
Да поверьте, это так. Лучший IMO, если большая часть вашей логики находится в фабричных или служебных объектах, но то же самое применимо, поскольку запущенные тесты могут получить доступ только к общедоступным свойствам или методам объекта. - person shaunhusain; 23.05.2016

Я знаю, что это старый случай, но вот решение, которое я использую.

Используйте «это» вашего контроллера

.controller('newController',['$scope',function($scope){
    var $this = this;
    $this.testMe = function(val){
        $scope.myVal = parseInt(val)+1;
    }
}]);

Вот тест:

describe('newDir', function(){
var svc, 
    $rootScope,
    $scope,
    $controller,
    ctrl;


 beforeEach(function () {
    module('myMod');
 });

 beforeEach(function () {
    inject(function ( _$controller_,_$rootScope_) {

        $controller = _$controller_;
        $rootScope = _$rootScope_;
        $compile = _$compile_;
        $scope = $rootScope.$new();
        ctrl = $controller('newController', {'$rootScope': $rootScope, '$scope': $scope });
    });
});

it('testMe inc number', function() {

    ctrl.testMe(10)
    expect($scope.myVal).toEqual(11);
});

});

Полный пример кода

person tmc    schedule 06.05.2015
comment
Есть ли причина, по которой вы используете $this, или это просто потому, что вам не нравится использовать такие переменные, как self? - person svassr; 22.12.2015
comment
Вы спрашиваете, почему я назвал свою переменную $this, а не сам? Нет никаких причин для моего выбора имен переменных. Self может облегчить чтение кода. - person tmc; 02.01.2016
comment
Да, это действительно был вопрос Спасибо. - person svassr; 05.01.2016
comment
+1, отличное решение. Кроме того, хорошо прочитайте this против $scope: stackoverflow.com/a/14168699/3123195 - person The DIMM Reaper; 08.06.2016
comment
Спасибо @TheDIMMReaper! Также спасибо за ссылку, хороший материал. - person tmc; 12.06.2016