2016-06-29 175 views
9

我想單元測試需要父組件和另一個模塊的控制器的AngularJS 1.5(與Webpack)組件的(子)控制器。需要父組件的控制器的角度1.5單元測試控制器

子控制器的結構:

function ChildController() { 
    var vm = this; 

    vm.searchText = ''; 

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

module.exports = ChildController; 

子組件:

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

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

module.exports = childComponent; 

所以我希望做的是模擬出該公司在childController的提交()所需的parentCtrl - 功能。我一直無法找到如何真正做到這一點。我找到了一些類似的孩子 - 家長指示解決方案並嘗試了這些解決方案如this child-parent directive example中所述通過僞造的HTML元素注入父控制器,並且基本上相同的stackoverflow solutions沒有結果。我的問題至少在兒童和父母控制器處於不同模塊的事實上有所不同。我想範圍技巧並不是那麼多的Angular 1.5風格?

我的茉莉花測試的骨架沒有我的失敗嘗試模擬:

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

導致TypeError: Cannot read property 'submitTextSearch' of undefined。我應該做些什麼來模擬父控制器?憑藉我在Angular方面的有限經驗,我沒有想法。

回答

4

在你的情況下,你添加parentCtrl作爲你的組件的依賴性,所以爲了測試它,你還必須模擬父組件,並將其分配給控制器。所以,你需要做這樣的事情:

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

我試過這個,但不適合我。仍然得到「指令''所需的」控制器'',找不到!「。 –

+1

你確定你的業力配置?也許有些文件沒有被加載。 – asoriano

0

解決方案

在您的測試實例化一個新的作用域父控制器:

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

和在您的子控制器中,使用先前實例化的範圍實例化新範圍:

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

實施例:

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。

兒童控制器結構:

function ChildController() { 
    var vm = this; 

    vm.searchText = ''; 

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

module.exports = ChildController; 

兒童組件:

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*'); 

REFRENCES:

AngularJS documentation - Testing Controllers

AngularJS documentation - $componentController

Unit Testing Angular Components with $componentController

2

使用下面的代碼會得到它的初始化,請檢查工作茉莉花單元測試Plunker

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

而且你的測試用例應該如下圖所示:

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

    }); 
});