18

Wir haben wenige Methoden in Angular Controller, die nicht auf der Scope-Variable sind.Wie können wir nicht-Winkel-Controller-Methoden testen?

Weiß jemand, wie wir diese Methoden in Jasmine-Tests ausführen oder aufrufen können?

Hier ist der Hauptcode.

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

Jetzt in meinem Jasmin Test werden wir "handleSuccessOfAPI" und "handleFailureOfAPI" Methode übergeben, aber diese sind nicht definiert.

Hier ist Jasmin Testcode.

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

Antwort

8

Sie haben keinen Zugriff auf diese Funktionen. Wenn Sie eine benannte JS Funktion definieren ist es das gleiche, als ob Sie in diesem Fall

var handleSuccessOfAPI = function(){}; 

zu sagen wären, würde es ziemlich klar zu sehen, dass die var innerhalb des Blockes nur im Rahmen ist, und es gibt keine externe Referenz dazu von der Verpackungssteuerung.

Alle Funktionen, die als diskret (und daher getestet) bezeichnet werden könnten, stehen im $ scope des Controllers zur Verfügung.

+2

Korrekt. Außerdem sollten wir keine privaten Funktionen testen. Im Allgemeinen wird 'init()' mit Einheitsdaten getestet, die sicherstellen, dass 'handleSuccessOfAPI' oder' handleFailureOfAPI' aufgerufen wird. Gespiegelte Objekte/Daten sollten den Ausführungspfad steuern. – dmahapatro

+0

Ich sehe $ scope, wie die Funktion/Variable öffentlich gemacht wird (wenn man sie mit etwas wie Java vergleicht). Ich bin mit Komponententests in Java nicht sehr vertraut, aber "teste ich nicht private Funktionen", was Sie normalerweise in Java tun? – Chris

+0

Chris, ich habe nur begrenzte Erfahrung beim Schreiben von Tests im Allgemeinen, habe einige JUnit-Tests geschrieben, aber ich bin keineswegs ein Experte im Testen oder so. Ich stelle mir vor, da die privaten Funktionen nicht offengelegt werden, wenn Sie eine Instanz eines Objekts instanziieren, befinden Sie sich immer noch unter der gleichen Einschränkung, dass Sie nur die Dinge testen können, die öffentlich zugänglich sind. Ich denke, dass dies letztendlich sinnvoll ist, da Sie sich wirklich mit einem Codeabschnitt beschäftigen, der eine Aufgabe in einer Art Black Box abschließt, wenn Sie einen Test schreiben, also wenn ich x voraussage, aber die Implementierungsdetails nicht eine Sorge. – shaunhusain

9

Ich weiß, das ist ein alter Fall, aber hier ist die Lösung, die ich verwende.

die 'this' Verwenden des Controllers

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

Hier ist der Test:

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

});

Full Code Example

+0

Gibt es einen Grund, warum Sie '$ this' verwenden, oder ist es nur, weil Sie nicht gerne Variablen wie' self' verwenden? – svassr

+0

Fragen Sie, warum ich meine Variable "$ this" genannt habe, anstatt sie "self" zu nennen? Es gibt keinen Grund für meine Wahl in Variablennamen. "Self" könnte Code leichter lesbar machen. – tmc

+0

Ja, das war die Frage in der Tat Danke – svassr

Verwandte Themen