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
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']);
})();
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 });
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?
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.
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();
}));
});