2016-06-29 4 views
9

Ich versuche, einen (Kind-) Controller einer AngularJS 1.5-Komponente (mit Webpack) zu testen, die eine Elternkomponente und einen Controller von einem anderen Modul benötigt.Angular 1.5-Unit-Testcontroller, der den Controller der übergeordneten Komponente benötigt

Kinderreglerstruktur:

function ChildController() { 
    var vm = this; 

    vm.searchText = ''; 

    vm.submit = function() { 
    var data = {}; 
    data['srch'] = vm.searchText; 
    vm.parentCtrl.submitTextSearch(data); 
    }; 
} 

module.exports = ChildController; 

Kinder Komponente:

var template = require('./child.html'); 
var controller = require('./child.controller'); 

var childComponent = { 
    require: { 
    parentCtrl: '^parent' 
    }, 
    template: template, 
    controller: controller, 
    controllerAs: 'vm' 
}; 

module.exports = childComponent; 

was So würde ich tun ist, mag die parentCtrl zu verspotten, die in der childController der submit() erforderlich ist - Funktion. Ich konnte nicht herausfinden, wie ich das eigentlich machen sollte. Ich habe einige ähnliche Kinder-Eltern-Richtlinien-Lösungen gefunden und diese, z. Injizieren des Eltern-Controllers durch ein gefälschtes HTML-Element, wie in this child-parent directive example beschrieben, und im Grunde dasselbe stackoverflow solutions ohne Ergebnisse. Meine Probleme unterscheiden sich zumindest dadurch, dass sich der Kind- und Eltern-Controller in verschiedenen Modulen befinden. Und ich denke, Scope-Tricks sind nicht so viel Angular 1.5-Stil?

Das Skelett meines Jasmin Test ohne meine gescheitert mock Versuche:

describe('child component', function() { 
    describe('child controller', function() { 
    var controller; 
    beforeEach(angular.mock.module('child')); 
    beforeEach(inject(function(_$componentController_) { 
     controller = _$componentController_('child'); 
    })) 
    it('should work', function() { 
     controller.searchText = "test"; 
     controller.submit(); 
    }) 
    }) 
}) 

Die in TypeError: Cannot read property 'submitTextSearch' of undefined führt. Was genau sollte ich tun, um den übergeordneten Controller zu verspotten? Mit meiner begrenzten Erfahrung in Angular habe ich keine Ideen mehr.

Antwort

4

In Ihrem Fall fügen Sie parentCtrl als Abhängigkeit von Ihrer Komponente hinzu, also müssen Sie, um es zu testen, auch die Mutterkomponente vortäuschen und sie dem Controller zuweisen. Also würden Sie brauchen so etwas wie zu tun:

beforeEach(inject(function(_$componentController_) { 
    controller = _$componentController_('child'); 
    parentCtrl = _$componentController_('parent'); 
    controller.parentCtrl = parentCtrl; 
})) 
+0

Ich habe das versucht, aber funktioniert nicht für mich. Immer noch "Controller '', benötigt von Direktive '', kann nicht gefunden werden!". –

+1

Sind Sie sich Ihrer Karma-Konfiguration sicher? Vielleicht werden einige Dateien nicht geladen. – asoriano

0

1. Lösung

In Ihrem Test die übergeordnete Steuerung mit einem neuen Bereich instanziiert:

mainScope = $rootScope.$new(); 
$controller('ParentController', {$scope: mainScope}); 

und Initiieren Sie in Ihrem untergeordneten Controller einen neuen Bereich mithilfe des zuvor instanziierten Bereichs:

childScope = mainScope.$new(); 
$controller('ChildController', {$scope: childScope}); 

Beispiel aus der AngularJS documentation:

describe('state', function() { 

    var mainScope, childScope, grandChildScope; 

    beforeEach(module('myApp')); 

    beforeEach(inject(function($rootScope, $controller) { 
     mainScope = $rootScope.$new(); 
     $controller('MainController', {$scope: mainScope}); 
     childScope = mainScope.$new(); 
     $controller('ChildController', {$scope: childScope}); 
     grandChildScope = childScope.$new(); 
     $controller('GrandChildController', {$scope: grandChildScope}); 
    })); 

    it('should work', function() { 
     grandChildScope.searchText = "test"; 
     grandChildScope.submit(); 
    }); 
}); 

2. Lösung

Child Reglerstruktur:

function ChildController() { 
    var vm = this; 

    vm.searchText = ''; 

    vm.submit = function() { 
    var data = {}; 
    data['srch'] = vm.searchText; 
    vm.parentCtrl.submitTextSearch(data); 
    }; 
} 

module.exports = ChildController; 

Child-Komponente:

var template = require('./child.html'); 
var controller = require('./child.controller'); 

    var childComponent = { 
     bindings: { 
     searchText: 'test' 
     }, 
     template: template, 
     controller: controller, 
     controllerAs: 'vm' 
    }; 

module.exports = childComponent; 

var ChildController = $componentController('childComponent', null, {...}); 
ChildController.$onInit(); 
expect(ChildController.searchText).to.equal('test'); 
expect(ChildController.submit()).to.equal('*expected result value should come here*'); 

Literaturverweise:

AngularJS documentation - Testing Controllers

AngularJS documentation - $componentController

Unit Testing Angular Components with $componentController

2

den Code unten verwenden wird es, initialisiert und bitte die Arbeits Jasmine Unit-Test Plunker

var ctrP = $componentController('parentComp'); 
var ctrl = $componentController('childComp', {}, { 
    parentCtrl: ctrP 
}); 

Und Ihren Testfall überprüfen soll, wie unten gezeigt:

'use strict'; 

describe('component: heroDetail', function() { 
    var $componentController, $compile, $rootScope; 

    beforeEach(module('plunker')); 
    beforeEach(inject(function(_$componentController_) { 
    $componentController = _$componentController_; 
    })); 

    it('should expose a `hero` object', function() { 
    var ctrP = $componentController('parentComp'); 
    console.log(ctrP); 
    var ctrl = $componentController('childComp', {}, { 
     parentCtrl: ctrP 
    }); 
    console.log(ctrl); 
    ctrl.submit('some data'); 
    expect(ctrl.parentCtrl.searchText).toEqual('some data'); 

    }); 
});