I have a controller test that depends on the Angular $routeParams service:
var $routeParams, MainCtrl, scope;
beforeEach(inject(function ($controller, $rootScope, $injector, $templateCache) {
scope = $rootScope.$new();
$routeParams = $injector.get('$routeParamsMock');
MainCtrl = $controller('MainCtrl', {
$scope: scope,
$routeParams: $routeParams,
});
}));
it('should load a pg from $routeParams', function(){
scope.userData = {};
$routeParams._setPg('PG_FIRST');
scope.$digest();
timeout.flush();
expect(scope.userData.pg).toBe(0);
$routeParams._setPg('PG_SECOND');
scope.$digest();
timeout.flush();
expect(scope.userData.pg).toBe(1);
});
$routeParamsMock:
!(function(window, angular){
'use strict';
angular.module('vitaApp')
.service('$routeParamsMock', function() {
var _pg = null;
return{
pg: _pg,
_setPg: function(pg){
_pg = pg;
}
}
});
})(window, window.angular);
When debugging the test, I was surprised to find out that $routeParamsMock.pg was returning null every single time, even though I called _setPg with a different value.
Is it because null is considered a primitive (with a type of object...), and thus passed by value?, or perhaps because Angular is copying the object that is passed to the $controller service?.
The solution I am looking for is preferably one that won't require to instanciate different controllers per different test scenerios. eg:
MainCtrl = $controller('MainCtrl', {
$scope: scope,
$routeParams: {'pg': 'PG_FIRST'},
});
MainCtrl = $controller('MainCtrl', {
$scope: scope,
$routeParams: {'pg': 'PG_SECOND'},
});
The thing is, what you don't want to do, is probably the best solution you have. A mock
makes sense when what you want to mock is kinda complex. Complex dependency with methods, lot of states, etc. For a simple object like $routeParams
it makes all the sense of the world to just pass a dummy object to it. Yes it would require to instantiate different controllers per test, but so what?
Structure your tests in a way that makes sense, makes it readable and easy to follow.
I suggest you something like:
describe('Controller: Foo', function() {
var $controller, $scope;
beforeEach(function() {
module('app');
inject(function($rootScope, _$controller_) {
$scope = $rootScope.$new();routeParams = {};
$controller = _$controller_;
});
});
describe('With PG_FIRST', function() {
beforeEach(function() {
$controller('Foo', { $scope: $scope, $routeParams: {'PG': 'PG_FIRST'}});
});
it('Should ....', function() {
expect($scope.something).toBe('PG_FIRST');
});
});
describe('With PG_SECOND', function() {
beforeEach(function() {
$controller('Foo', { $scope: $scope, $routeParams: {'PG': 'PG_SECOND'}});
});
it('Should ....', function() {
expect($scope.something).toBe('PG_SECOND');
});
});
});
With a good test organization, I can say that I like this test easy to follow.
http://plnkr.co/edit/5Q3ykv9ZB7PuGFMfWVY5?p=preview
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With