So I am testing a controller, which is referencing a property specified as ngModel in DOM. But while I am testing my controller, I don't have the template. So whenever $scope.foo.property is being accessed in the controller, it throws an error.
Asked
Active
Viewed 1,957 times
1
-
Can you provide a mock template? – Robert Harvey Jul 31 '13 at 17:34
-
Mock template, well I am testing the controller, why should I need the mock template for ? The tutorials state, "In angular the controllers are strictly separated from the DOM " – M T Jul 31 '13 at 17:45
-
Indeed. Which raises the question, why do you need the template? – Robert Harvey Jul 31 '13 at 17:46
-
So in you are suggesting if a property foo.property is being accessed in controller, then I am breaking the convention and making the code untestable ? – M T Jul 31 '13 at 17:56
2 Answers
1
In your test, you can define your property before instantiate your controller :
it('should mock ng-model', inject(function($rootScope, $controller) {
$rootScope.foo = {
property: 'mock value'
};
$controller('myController', {$scope: $rootScope});
})));

Bastien Caudan
- 4,482
- 1
- 17
- 29
-
THe foo.property is of type NgModelController, not sure how to create instance or mock that. – M T Aug 01 '13 at 04:02
-
You want to test your controller and its interactions with this property, not the ngModelController ? – Bastien Caudan Aug 01 '13 at 08:11
-
This is something I did, say for instance I have a ngModelConroller instance being referred in the controller, so I would mock the ngModelController instance, with mocked methods say $setValidity and injected it into the scope and passed it around the controller. So this way I can test if the method $setValidity was called, if my functional spec conclues this. – M T Aug 04 '13 at 17:19
-
I think that if you want to use ngModelController you should be in a directive linking function and not in a module controller. Maybe this can help : http://stackoverflow.com/questions/14115701/angularjs-create-a-directive-that-uses-ng-model – Bastien Caudan Aug 05 '13 at 17:47
0
Controllers and views (templates) are two separate things in Angular applications. What glues them together is the scope (or model). So, to test a controller all you need is a fake scope to pass to the controller function.
Here's a very simple example using a global controller (just to keep things easier to understand - don't use global controllers in production code) and a pseudo test function:
function MyCtrl($scope) {
$scope.bar = $scope.foo.property + 1;
}
function test() {
var scope = { foo: { property: 1 }};
MyCtrl(scope);
expect(scope.bar).toBe(2);
}
It gets a little bit more complicated than that when the controller is defined within an module, but that's another story.

Michael Benford
- 14,044
- 3
- 60
- 60