How to mock AngularJS $resource with $promise.then in jasmine - angularjs

I have a a factory which uses Angular resource to make API call. I then created a function called getObjectById and use the factory to query for that object and then modify the object before returning.
Service:
return getObjectById: function(id) {
return objectFactory.getById({ id: id }).$promise.then(function(response) {
return modifyObject(response.object);
});
}
I want to test that modifyObject() is working correctly but modifyObject is a private function.
So to test it i'm trying to mock object the response object factory is returning with a spy.
Test:
beforeEach(function() {
inject(function(objectFactory, $q) {
spyOn(objectFactory, 'getById').and.returnValue({ $promise: $q.when(readJSON('test/resources/object.json'))});
});
});
But everytime I run the test I get the error:
TypeError: Cannot read property 'returnValue' of undefined
If I can get any help on getting it to work that will be great. Even suggestion if i'm doing the layout wrong. Using latest Version Of Jasmine

It's a very late answer, but I just ran into the same issue in an AngularJS / Angular hybrid app. We are using jasmine v1, but imported jasmine v2 typing. Which means the TypeScript would not compile with v1 syntax but would fail with TypeError: Cannot read property 'returnValue' of undefined.
The jasmine version needs to match the typing:
"karma-jasmine": "0.1" means jasmine v1 and requires "#types/jasmine": "^1.3.0"
"karma-jasmine": "0.3" would be jasmine v2 and requires "#types/jasmine": "2.8"

You're missing the closing bracket
spyOn(objectFactory, 'getById').and.returnValue({ $promise: $q.when(readJSON('test/resources/object.json'))});

Related

Promises are not resolved in Jasmine using Karma

I have a problem with a small karma unit test that should check a simple decryption/encryption service.
The thing is, if I call the following code "manual" (i.e., within my running angular app) everything is fine and I receive the expected test output:
this.encryptDataAsync('Hello World of Encryption','b4b63cd1a64dbef72fefe2eb3e3fc3eb').then((encryptedValue : string) : void => {
console.log('1',encryptedValue);
this.decryptDataAsync(encryptedValue,'b4b63cd1a64dbef72fefe2eb3e3fc3eb').then(function(decryptedValue : string) : void{
console.log('2',decryptedValue);
});
});
As soon as I try to run this Karma/Jasmine unit test
describe('simple encryption/decryption', function() {
var results = '';
beforeEach(function(done) {
_cryptoService.encryptDataAsync('ABC','b4b63cd1a64dbef72fefe2eb3e3fc3eb').then(function (encryptedValue){
console.log('1');
_cryptoService.decryptDataAsync(encryptedValue,'b4b63cd1a64dbef72fefe2eb3e3fc3eb').then(function(decryptedValue){
console.log('2');
results = decryptedValue;
done();
});
});
});
it("check results", function(done){
expect(results).toBe('ABC');
done();
}, 3000);
});
I never reach console.log('1') nor '2'. I can confirm this while debugging the unit test. However, this is the only unit test that fails in the complete suite, so I guess it won't by a problem with modules, etc.
Is there a general problem with my test case? I would have expected that I can use the then functions to handle my test case and, afterwards, call the done() function to invoke the assertion part.
Update/Edit:
The service uses webcrypto as a library. It is complete independent of angular besides being an angular service (so, no variables on scopes, etc)
I needed to call scope.apply since "$q is integrated with the $rootScope.Scope Scope model observation mechanism in angular, which means faster propagation of resolution or rejection into your models and avoiding unnecessary browser repaints, which would result in flickering UI."

Can't get this unit test (on a helper) to run without exceptions - AngularJS, Karma, Jasmine

I'm new to Angular and Karma and every site out there seems to recommend a different way of writing unit tests, which makes all of this very confusing. Help is appreciated!
I have a helper class that has a dependency on a service class. I am writing a unit test for the helper class. I have this:
module("myModule");
it('works!', inject(function(myHelper) {
module(function($provide) {
$provide.service('myService', function() {
payload = spyOn(myService, 'getPayload').andReturn(
{id: 1 });
});
});
expect(myHelper.getSomeData()).toEqual(exepectedData);
}));
The exception I'm getting when running the test is:
Error: [$injector:unpr] Unknown provider: myHelperProvider <- myHelper
I've tried all different ways of doing this, but haven't gotten it to work yet.
Try calling module("myModule"); in a beforeEach, i.e.:
beforeEach(module('myModule'));
You may have luck with actually calling the function returned by module("myModule"), i.e.:
module("myModule")();
... but have never tried this and I have serious doubts.
Also I always enclose my it() specs in a describe() block; not sure if strictly necessary though.

Testing local methods containing service calls using Jasmine

I am facing an issue with testing a local method in my Angular JS controller.
I need to test retrieveRuleDetails method which contains a service call, but not able to proceed. Please help to test the below code:
var retrieveRuleDetails = function(feeId, ruleId) {
$rootScope.triggerLoading(true);
FeesRulesService.getRule(feeId, ruleId)
.then(getRuleSuccess)
.catch(getRuleFail);
};
I think best would be to pass FeesRulesService as a paramter - a spy in jasmine
and than to test getRule is invoked
FeesRulesServiceMock= {
getRule: function(feeId,ruleId) {
}
};
spyOn(FeesRulesServiceMock, 'getRule');
retrieveRuleDetails(feeId,ruleId,FeesRulesServiceMock)
it("bla bla",function(){
expect(FeesRulesServiceMock.getRule).toHaveBeenCalled();
expect(FeesRulesServiceMock.getRule).toHaveBeenCalledWith(feeId,ruleId);
});

How to mock AngularJS $resource with $promise.then in jasmine specs

I use $resource to set up some API calls, and while testing I have adopted the general approach of injecting $qand then doing
mockMyService.doSomethingAsync.andReturnValue($q.when(successResponse))
This has been working out pretty well, however, I have a method that looks like the following:
# MyService
MyService.doSomethingAsync(params).$promise.then ->
$scope.isLoading = false
# MyService Spec
mockMyService =
doSomethingAsync: jasmine.createSpy('doSomethingAsync')
it 'calls service #doSomethingAsync', ->
inject ($q) -> mockMyService.doSomethingAsync.and.returnValue($q.when(response))
controller.methodThatWrapsServiceCall()
scope.$apply()
expect(mockMyService.doSomethingAsync).toHaveBeenCalled()
and unfortunately the mocking strategy outlined above doesn't seem to work when a $promise.then is chained at the end. I end up with the following error:
TypeError: 'undefined' is not an object (evaluating 'MyService.doSomethingAsync(params).$promise.then')
Methods that simply end with doSomethingAsync().$promise pass the tests without issues using this mocking strategy.
(Other info: These are Jasmine tests run with Karma and PhantomJS)
Actually, figured it out!
I just changed my mock to return and.returnValue( { $promise: $q.when(response) } )

Testing AngularJS Service with Jasmine throw an error with parsed.protocol

I'm trying to test some services that receive some modifications. Some of them are using $http service, and only one of them is populating an unknown - and a not understandable - issue.
Let me expose.
it('must reject the promise with an explanation if the required path is not found', function() {
$httpBackend.whenGET('http://localhost/testok').respond(function () {
return [200, mockedRemoteResponse, {}];
});
var promise = apiDataExtractor.extractRemoteData('ok', 'toto');
$httpBackend.flush();
});
Running this code throught Jasmine, we got this:
I do not have ANY idea of what appends. I try to change injection order, try to erase and rewrite my test, there is something here I'm missing.
Can anyone help?
The error you are seeing is probably due to a call to $http.get with undefined as the url (you might have forgotten to provide parameters to $http.get() inside apiDataExtractor.extractRemoteData?)
Try debugging your code and see what are the parameters you are giving the $http.get method.

Resources