问题
I want to test an AngularJS directive declared like this
app.directive('myCustomer', function() {
return {
template: 'cust.html'
controller: 'customerController'
};
});
In the test I would like to inject (or override) the controller, so that I can test just the other parts of the directive (e.g. the template). The customerController
can of course be tested separately. This way I get a clean separation of tests.
- I have tried overriding the controller by setting the controller property in the test.
- I have tried injecting the
customController
using$provide
. - I have tried setting
ng-controller
on the html directive declaration used in the test.
I couldn't get any of those to work. The problem seems to be that I cannot get a reference to the directive until I have $compile
d it. But after compilation, the controller is already set up.
var element = $compile("<my-customer></my-customer>")($rootScope);
回答1:
I think there is a simpler way than the accepted answer, which doesn't require creating a new module.
You were close when trying $provide
, but for mocking controllers, you use something different: $controllerProvider
. Use the register()
method in your spec to mock out your controller.
beforeEach(module('myApp', function($controllerProvider) {
$controllerProvider.register('customerContoller', function($scope) {
// Controller Mock
});
});
回答2:
One way is to define a new module (e.g. 'specApp') that declares your app (e.g. 'myApp') as a dependency. Then register a 'customerController' controller with the 'specApp' module. This will effectively "hide" the customerController of 'myApp' and supply this mock-controller to the directive when compiled.
E.g.:
Your app:
var app = angular.module('myApp', []);
...
app.controller('customerController', function ($scope,...) {
$scope = {...};
...
});
app.directive('myCustomer', function () {
return {
template: 'cust.html',
controller: 'customerController'
};
});
Your spec:
describe('"myCustomer" directive', function () {
$compile;
$newScope;
angular.module('specApp', ['myApp'])
/* Register a "new" customerController, which will "hide" that of 'myApp' */
.controller('customerController', function ($scope,...) {
$scope = {...};
...
});
beforeEach(module('specApp'));
it('should do cool stuff', function () {
var elem = angular.element('<div my-customer></div>');
$compile(elem)($newScope);
$newScope.$digest();
expect(...
});
});
See, also, this working demo.
来源:https://stackoverflow.com/questions/21218273/how-to-inject-a-controller-into-a-directive-when-unit-testing