I am trying to write unit tests for a controller that gets a promise from a service, but in Jasmine I am getting:
TypeError: Cannot read property 'then' of undefined
In controller I call .then()
on returned promise from service.
Can anybody help please? I am surely missing something obvious.
Here is a plunk:
'use strict';
describe('Language controller', function() {
var scope, translationService, createController;
beforeEach(function() {
var mockTranslationService = {};
module('dictApp', function($provide) {
$provide.value('translationService', mockTranslationService);
});
inject(function($q) {
mockTranslationService.languages = [
{
name: 'slovak'
},
{
name: 'czech'
}
];
mockTranslationService.languagesWithWords = [{
name: 'slovak',
words: [{
key: 'Car',
translation: 'Auto',
createdOn: 0
}, {
key: 'Flower',
translation: 'Kvet',
createdOn: 0
}]
}, {
name: 'czech',
words: {
key: 'Plaza',
translation: 'Namesti',
createdOn: 0
}
}];
mockTranslationService.getLanguages = function() {
var deferred = $q.defer();
deferred.resolve(this.languages);
return deferred.promise;
};
});
});
beforeEach(inject(function($controller, $rootScope, _translationService_) {
scope = $rootScope.$new();
translationService = _translationService_;
createController = function () {
return $controller('LanguageCtrl',
{$scope: scope, translationService: translationService});
};
scope.$digest();
}));
it('should get the language array', function() {
spyOn(translationService, 'getLanguages');
createController();
expect(translationService.getLanguages).toHaveBeenCalled();
});
});
and this is the controller:
dictControllers.controller('LanguageCtrl', ['$scope', 'translationService', function($scope, translationService){
$scope.getLanguages = function() {
translationService.getLanguages().then(function(){
$scope.languages = translationService.languages;
});
};
$scope.getLanguages();
$scope.getWords = function(language) {
translationService.getWords(language);
};
$scope.newWord = {};
$scope.addWord = function(language) {
translationService.addWord($scope.newWord, language);
$scope.newWord = {};
};
}]);
I am trying to write unit tests for a controller that gets a promise from a service, but in Jasmine I am getting:
TypeError: Cannot read property 'then' of undefined
In controller I call .then()
on returned promise from service.
Can anybody help please? I am surely missing something obvious.
Here is a plunk: http://plnkr.co/edit/vJOopys7pWTrTQ2vLgXS?p=preview
'use strict';
describe('Language controller', function() {
var scope, translationService, createController;
beforeEach(function() {
var mockTranslationService = {};
module('dictApp', function($provide) {
$provide.value('translationService', mockTranslationService);
});
inject(function($q) {
mockTranslationService.languages = [
{
name: 'slovak'
},
{
name: 'czech'
}
];
mockTranslationService.languagesWithWords = [{
name: 'slovak',
words: [{
key: 'Car',
translation: 'Auto',
createdOn: 0
}, {
key: 'Flower',
translation: 'Kvet',
createdOn: 0
}]
}, {
name: 'czech',
words: {
key: 'Plaza',
translation: 'Namesti',
createdOn: 0
}
}];
mockTranslationService.getLanguages = function() {
var deferred = $q.defer();
deferred.resolve(this.languages);
return deferred.promise;
};
});
});
beforeEach(inject(function($controller, $rootScope, _translationService_) {
scope = $rootScope.$new();
translationService = _translationService_;
createController = function () {
return $controller('LanguageCtrl',
{$scope: scope, translationService: translationService});
};
scope.$digest();
}));
it('should get the language array', function() {
spyOn(translationService, 'getLanguages');
createController();
expect(translationService.getLanguages).toHaveBeenCalled();
});
});
and this is the controller:
dictControllers.controller('LanguageCtrl', ['$scope', 'translationService', function($scope, translationService){
$scope.getLanguages = function() {
translationService.getLanguages().then(function(){
$scope.languages = translationService.languages;
});
};
$scope.getLanguages();
$scope.getWords = function(language) {
translationService.getWords(language);
};
$scope.newWord = {};
$scope.addWord = function(language) {
translationService.addWord($scope.newWord, language);
$scope.newWord = {};
};
}]);
Share
Improve this question
edited Jun 7, 2015 at 17:24
Ondrej Slinták
32k21 gold badges96 silver badges127 bronze badges
asked Feb 9, 2015 at 9:58
Július RetzerJúlius Retzer
1,0751 gold badge11 silver badges25 bronze badges
1 Answer
Reset to default 4Use spyOn(mockTranslationService, 'getLanguages').and.returnValue(deferred.promise);
instead. It also makes more sense to resolve the promise after the getLocations() has been called rather than before getLocations()
returns the promise. You should also check the languages.
inject(function($q) {
deferred = $q.defer();
mockTranslationService.languages = [
{
name: 'slovak'
},
{
name: 'czech'
}
];
mockTranslationService.languagesWithWords = [{
name: 'slovak',
words: [{
key: 'Car',
translation: 'Auto',
createdOn: 0
}, {
key: 'Flower',
translation: 'Kvet',
createdOn: 0
}]
}, {
name: 'czech',
words: {
key: 'Plaza',
translation: 'Namesti',
createdOn: 0
}
}];
mockTranslationService.getLanguages = function () {
};
spyOn(mockTranslationService, 'getLanguages').and.returnValue(deferred.promise);
});
it('should get the language array', function() {
createController();
deferred.resolve();
scope.$digest();
expect(translationService.getLanguages).toHaveBeenCalled();
expect(scope.languages).toEqual(translationService.languages);
});
Plunkr