Jasmine's spy throwing is not a function error
Seems like a typo if this is the real code. Change the appropriated part to:
shoppingData = {
getAllItems: jasmine.createSpy('getAllItems'),
addAnItem: jasmine.createSpy('addAnItem'),
removeItem: jasmine.createSpy('removeItem')
};
Just changed the function to an object and changed the ;
for ,
.
UPDATE 1:
Consider only spying at the existing object:
var deferred, _shoppingData;
beforeEach(module('shopping'));
beforeEach(inject(function(shoppingData, $q) {
_shoppingData = shoppingData;
deferred = $q.defer();
spyOn(shoppingData, 'getAllItems').andReturn(deferred.promise);
}));
it('should have called shoppingData.getAllItems', function() {
expect(_shoppingData.getAllItems).toHaveBeenCalled();
});
S. Ravi Kiran
Software developer. Very passionate about Microsoft Technologies and Web Programming
Updated on June 04, 2022Comments
-
S. Ravi Kiran almost 2 years
I have an Angular JS application with a module and some services in it. My controller uses these services. In Jasmine test cases, I created a mock of a service using Jasmine's
createSpy
. Following is the mocked service:beforeEach(module(function ($provide) { shoppingData = function () { getAllItems: jasmine.createSpy('getAllItems'); addAnItem: jasmine.createSpy('addAnItem'); removeItem: jasmine.createSpy('removeItem'); }; $provide.value('shoppingData', shoppingData); }));
Controller calls the
getAllItems
function as soon as an object is created. I created anotherbeforeEach
block that creates an object of the controller. Following is the test block to check ifgetAllItems
is called:it("Should call getAllItems function on creation of controller", function () { expect(shoppingData.getAllItems).toHaveBeenCalled(); });
When I run the spec runner page on browser, the test fails with following error: TypeError: 'shoppingData.getAllItems' is not a function
I saw several similar example where this kind of test works without any issue. Can anyone point what is missing or what is going wrong here?
Update: I created a plunker with the part that fails
-
S. Ravi Kiran about 11 yearsI had tried this approach too. But it throws an error saying: 'Cannot convert shoppingData.getAllItems' to an object
-
Caio Cunha about 11 yearsMaybe you're doing something else wrong. I made a working Plnker here. Look at it. If you can't understand anything, let me know and I'll try to explain. Maybe you forgot to create the controller, or inject something. Only when you first inject something, the module will be created and shoppingData will be avaialable.
-
S. Ravi Kiran about 11 yearsThanks for your effort. After tweaking your plunker a bit and analyzing my code I got to know that it is failing because the function inside which I am calling getAllItems uses the returned object to call then() function. I forked your plnkr and created a demo. You can access it from here: plnkr.co/edit/BenU8lJtICS2uNyrtjns?p=preview
-
Caio Cunha about 11 yearsThen all you got to do is to mock the return value with
andReturn
, take a look at Jasmine docs. Add this line just after creating theshoppingData
object:shoppingData.getAllItems.andReturn({then: function(){}});
. But, looking at this new angle, you don't need to mock the entire object, just inject andspyOn
it inbeforeEach
. Updated your Plunkr appSpec. Consider also reading $httpBackend mock. -
S. Ravi Kiran about 11 yearsThanks Caio. I know about $httpBackend. I placed the logic in a separate service to keep the controller free from data-access logic. I didn't check Jasmine's docs properly. Will go through it.