AngularJS and Jasmine: mocking services - javascript

I am having trouble mocking the dependency of the following service "broadcaster" over the service "pushServices".
angular.module('broadcaster', ['pushServices']);
angular.module('broadcaster').service('broadcaster', [
'$rootScope', '$log', 'satnetPush',
function ($rootScope, $log, satnetPush) {
// .. contents ..
};
};
The Jasmine spec is as follows:
describe('Test Broadcaster Service', function () {
'use strict';
var broadcasterService, mockPushService;
beforeEach(module('broadcaster'));
beforeEach(inject(function($injector) {
broadcasterService = $injector.get('broadcaster');
mockPushService = {
getSomething: function () { return 'mockReturnValue'; }
};
module(function ($provide) {
$provide.value('satnetPush', mockPushService);
});
}));
it('should return a non-null broadcaster object', function () {
expect(broadcasterService).not.toBeNull();
});
});
The error that I get is the typical "Unknown provider":
PhantomJS 1.9.8 (Linux) Test Broadcaster Service should return a non-null broadcaster object FAILED
Error: [$injector:unpr] Unknown provider: $pusherProvider <- $pusher <- satnetPush <- broadcaster
http://errors.angularjs.org/1.3.14/$injector/unpr?p0=%24pusherProvider%20%3C-%20%24pusher%20%3C-%20satnetPush%20%3C-%20broadcaster
What am I doing wrong? How should I be injecting the dependency instead?

The key is to $provide your mock service before you get the service under test from $injector. Then the 'satnetPush' will exist:
describe('Test Broadcaster Service', function () {
'use strict';
var broadcasterService, mockPushService;
beforeEach(function() {
module('broadcaster');
module(function ($provide) {
mockPushService = {
getSomething: function () { return 'mockReturnValue'; }
};
$provide.value('satnetPush', mockPushService);
});
inject(function($injector) {
broadcasterService = $injector.get('broadcaster');
})
});
it('should return a non-null broadcaster object', function () {
expect(broadcasterService).not.toBeNull();
});
});
Here's a working fiddle

Related

Injecting dependencies into Angular services for testing

I'm trying to do some test driven development of an angular service I'm writing using Jasmine. However, I seem to have stumbled at the first hurdle, and I cannot get my $resource dependency to resolve.
The error I get is
Unknown provider: $resourceProvider <- $resource <- lookupService
My code is as follows
Module:
(function() {
'use strict';
angular
.module('common', ['ngSanitize', 'ngAnimate']);
})();
Service:
(function() {
'use strict';
angular
.module('common')
.service('lookupService', lookupService);
lookupService.$inject = ['$resource', 'api'];
function lookupService($resource, api) {
return {
getLookup: getLookup
};
function getLookup() {
return "something";
}
}
})();
Test:
describe('Service tests',
function () {
var lookupService, mockApi, $httpBackend;
//mocks
beforeEach(function () {
mockApi = { getUri: jasmine.createSpy() };
angular.mock.module('common',
function ($provide) {
$provide.value('api', mockApi);
});
});
//injects
beforeEach(function () {
inject(function ($injector) {
$httpBackend = $injector.get('$httpBackend');
lookupService = $injector.get('lookupService');
});
});
//tests
it('should be able to return something',
inject(function () {
expect(lookupService.getLookup()).toEqual("something");
}));
});//Service tests
The angular-resource.js file is included in my runner file. I'm not sure where I'm going wrong, any help would be appreciated.
Thanks
ngResource must be a dependency:
(function() {
'use strict';
angular
.module('common', ['ngSanitize', 'ngAnimate', 'ngResource']);
})();

Angular: Error: [$injector:unpr] Unknown provider: $scopeProvider <- $scope [duplicate]

This question already has answers here:
Angular Unit Test Unknown provider: $scopeProvider
(2 answers)
Closed 7 years ago.
Yet another question about injecting $scope into tests and services :-) Learning angular and using angular-seed application as a start.
I have extended my controller to have $scope but now my default angular seed tests are failing with
Error: [$injector:unpr] Unknown provider: $scopeProvider <- $scope
I don't understand is the error with my controller or with my tests...
View/Controller/Service
(function () {
"use strict";
angular.module("app.view1", ["ngRoute"])
.config(["$routeProvider",
function ($routeProvider) {
$routeProvider.when("/view1", {
templateUrl: "views/view1/view1.html",
controller: "View1Ctrl"
});
}
])
.factory("User", ["$http",
function ($http) {
var User = {};
User.get = function () {
return $http.get("/api/v1/user");
};
return User;
}
])
.controller("View1Ctrl", ["$scope", "User",
function ($scope, User) {
User.get().success(
function (response) {
$scope.user = response;
});
}
]);
}());
Test
'use strict';
describe('app.view1 module', function() {
beforeEach(module('app.view1'));
describe('view1 controller', function(){
it('should ....', inject(function($controller) {
//spec body
var view1Ctrl = $controller('View1Ctrl');
expect(view1Ctrl).toBeDefined();
}));
});
});
Application is working and I get to see data in HTML but tests are failing... all suggestions welcome!
I was missing $scope in the test, here is updated test that works:
'use strict';
describe('app.view1 module', function() {
beforeEach(module('app.view1'));
describe('view1 controller', function() {
it('should ....', inject(function($controller, $rootScope) {
//spec body
var $scope = $rootScope.$new(),
ctrl = $controller('View1Ctrl', {
$scope: $scope,
$User: {}
});
expect(ctrl).toBeDefined();
}));
});
});
Your are in a test, there is no DOM, and no $scope.
Your can deal with this by passing locals to the $controller service, like this :
var $scope = {};
var view1Ctrl = $controller('View1Ctrl', { $scope: $scope });

writing jasmine unit test for angular factory

I am trying to test an angular factory using jasmine and mocha however I keep getting undefined errors.
here is my factory:
(function() {
'use strict';
angular.module('app').factory('appFactory', appFactory);
appFactory.$inject = ['$http','$q'];
function appFactory($http,$q) {
return {
get: get
};
function get(someData) {
//....
}
}
})();
and here is my unit test using jasmine and mocha:
'use strict';
describe('Factory: appFactory', function() {
var http, appFactory;
var $rootScope, $scope;
beforeEach(function() {
angular.module('app');
});
beforeEach(inject(function($injector) {
$rootScope = $injector.get('$rootScope');
$scope = $rootScope.$new();
}));
beforeEach(inject(function() {
var $injector = angular.injector(['ngMock', 'ng', 'app']);
appFactory = $injector.get('appFactory');
}));
it('should be defined', inject( function() {
alert(appFactory);
}));
});
so my alert looks something like:
Object{get: function get(someData) {...}
how do I go about testing the functionality of my factory if this is returning an object?

Difference between "angualar.module" and "module" when unit-testing Angular

What is the difference between angual.module('app') and module('app')?
Here is the simple service and unit test in question:
Service
(function () {
"use strict"
var app = angular.module('app', []);
app.service('CustomerService', ['$http', function ($http) {
return {
getById: function (customerId) {
return $http.get('/Customer/' + customerId);
}
}
}]);
}());
Test
describe('Customer Service', function () {
var $rootScope,
$httpBackend,
service,
customerId = 1;
beforeEach(function () {
angular.module('app', ['ngMock']);
inject(function ($injector) {
$rootScope = $injector.get('$rootScope');
$httpBackend = $injector.get('$httpBackend');
$httpBackend.whenGET('/Customer/' + customerId).respond({ id: customerId, firstName: 'Joe', lastName: 'Blow' });
service = $injector.get('CustomerService');
});
});
afterEach(function () {
$httpBackend.verifyNoOutstandingRequest();
});
it('should get customer by id', function () {
var customer;
service.getById(1).then(function (response) {
customer = response.data;
});
$httpBackend.flush();
expect(customer.firstName).toBe('Sam');
});
});
module in the unit test framework refers to the mock angular.mock.module method (which is attached to window as a convenience). angular.module is the method that angular.mock.module mocks.

Unit testing in AngularJS with mock $resource

Trying to get some units tests in AngularJS (using jasmine & karma) working and struggling to comprehend dependency injection... current error message in karma reads 'Error: Argument 'fn' is not a function, got string'
app.js
angular.module('App', [ 'App.Services', 'App.Controllers', 'App.Directives']);
controller.js
angular.module('App.Controllers', []).
controller('MarketplaceCtrl', function ($scope, apiCall) {
apiCall.query({
type: 'engagement',
engagement_status__in: '0,1'
}, function(data) {
var engagements = {};
$.each(data.objects, function (i, engagement) {
engagements[engagement.lawyer_id] = engagement
});
$scope.engagements = engagements;
});
});
services.js
angular.module('App.Services', ['ngResource']).
factory('apiCall', function ($resource) {
return $resource('/api/v1/:type',
{type: '#type'},
{
query: {
method: 'GET',
isArray: false
}
}
);
});
controllerSpec.js
describe('controllers', function () {
beforeEach(
module('App', ['App.Controllers', 'App.Directives', 'App.Services'])
);
describe('MarketplaceCtrl', function () {
var scope, ctrl, $httpBackend;
beforeEach(inject(function (_$httpBackend_, $rootScope, $controller) {
$httpBackend = _$httpBackend_;
$httpBackend.expectGET('/api/v1/engagement?engagement_status__in=0,1').
respond([]);
scope = $rootScope.$new();
/* Why is MarketplaceCtrl not working? :( */
ctrl = $controller('MarketplaceCtrl', {$scope: scope});
}));
it('should have a MarketplaceCtrl controller', (function () {
expect(ctrl).not.to.equal(null);
}));
});
});
Ended up using this example https://github.com/tebriel/angular-seed/commit/b653ce8e642ebd3e2978d5404db81897edc88bcb#commitcomment-3416223
Basically:
describe('controllers', function(){
beforeEach(module('myApp.controllers'));
it('should ....', inject(function($controller) {
//spec body
var myCtrl1 = $controller('MyCtrl1');
expect(myCtrl1).toBeDefined();
}));
it('should ....', inject(function($controller) {
//spec body
var myCtrl2 = $controller('MyCtrl2');
expect(myCtrl2).toBeDefined();
}));
});

Categories