Как запускать $onInit или $onChanges в модульном тестировании компонентного контроллера Angular?
Я использую Angular 1.5.5 и Jasmine как тестовую структуру. В настоящее время я должен сделать что-то подобное, чтобы тест проходил:
function createController(bindings) {
return $componentController('myController', null, bindings);
}
beforeEach(inject(function (_$componentController_) {
$componentController = _$componentController_;
}));
describe('on pages updated', function () {
beforeEach(function () {
controller = createController({prop1: 0, prop2: 0});
controller.$onInit(); // you see I have to explitcitly call this $onInit function
});
it('should update isSelected and currentPage', function () {
expect(controller.prop1).toBe(0);
expect(controller.prop2).toBe(0);
controller.prop1= 1;
controller.prop2= 2;
controller.$onChanges(controller); // and $onChanges here as well
expect(controller.prop1).toBe(1);
expect(controller.prop2).toBe(2);
});
});
Ответы
Ответ 1
В github есть проблема относительно этого: https://github.com/angular/angular.js/issues/14129
В основном он работает по назначению, не вызывая $onInit
или $onChanges
автоматически.
нет смысла (или низкого смысла) для выполнения $onInit, я объясняю это: $componentController - это контроллеры экземпляров как замена для контроллера $, но вместо создания экземпляров контроллеров, зарегистрированных контроллеромProvider, он создает экземпляры контроллеры, зарегистрированные через директивы (те, которые удовлетворяют определению компонента). Итак, как только у вас есть экземпляр контроллера, вы можете вызывать вручную $onInit и весь жизненный цикл вашего контроллера, идея состоит в том, что вы тестируете контроллер, а не директиву (и ее отношения).
Ответ 2
Я не знаю, поможет ли это, но для тестирования компонентов я делаю следующее
beforeEach(module('templates'));
var element;
var scope;
beforeEach(inject(function ($rootScope, $compile) {
scope = $rootScope.$new();
scope.draw = new ol.source.Vector({ wrapX: false });
element = angular.element('<custom-element draw="draw"></custom-element>');
element = $compile(element)(scope);
}));
var controller;
beforeEach(inject(function ($rootScope, $componentController) {
scope = $rootScope.$new();
scope.draw = new ol.source.Vector({ wrapX: false });
controller = $componentController('customElement', {draw: new ol.source.Vector({ wrapX: false })}, { $scope: scope });
}));
и $onInit() и $onChanges() запускаются, когда они должны быть сами по себе
Ответ 3
Вам потребуется взять ссылку на контроллер из скомпилированной версии элемента. Как показано ниже:
describe('Component: Test Method', function () {
beforeEach(inject(function (_$rootScope_) {
scope = _$rootScope_.$new();
}));
it('should set value of selectedPackage to null after $onChanges event', inject(function ($compile) {
// Trigger 1st $onChanges
scope.selectedPackage = 'packageCode';
var element = angular.element('<select-my-tv selected-package="selectedPackage"></select-my-tv>');
element = $compile(element)(scope);
scope.$digest();
//Extract the Controller reference from compiled element
var elementController = element.isolateScope().$ctrl;
// Assert
expect(elementController.selectedPackage).toBeNull();
}));
});
});