Getting "Unsatisfied requests: DELETE" for my controller test. below are the code for my service, controller and test. tests are written using jasmine-karma and angular-mock. Thanks in advance.
service:
function deleteAsset(assetId) {
return $http.delete(baseUrl + '/delete/' + assetId).then(assetDeleted);
function assetDeleted(response) {
return response.data;
}
}
Controller:
(function () {
'use strict';
angular.module('tbApp').controller('assetEditCtrl', assetEditCtrl);
assetEditCtrl.inject = ['$routeParams', 'Campaign', 'User', '$location', 'Asset', '$window', '$scope', '$compile', 'ImageLibrary', 'Lists'];
function assetEditCtrl($routeParams, Asset, $window, $scope, $compile) {
function deleteAsset(assetId,assetType,assetName, el) {
//confirmation popup
CB.setProceedBoxCode("Are you sure you want to delete "+assetType+" "+assetName+"?", el, {OK: "Yes", CANCEL: "No", width: "400", title: "", callback: function (r, ele) {
if (r == true) {
Asset.deleteAsset(assetId).then(assetDeleted);
}
}});
function assetDeleted(data) {
backTodashbiard();
}
} } });
Test:
describe('assetEditCtrl', function() {
var scope, httpBackend, http, controller, vm, createController, assetId, el, assetType, assetName, compile;
var baseUrl = './webresources/assets';
beforeEach(module("tbApp"));
beforeEach(inject(function($rootScope, $httpBackend, $controller, $http, $compile) {
httpBackend = $httpBackend;
compile = $compile
scope = $rootScope.$new();
controller = $controller;
assetId= "EML1000006003";
campaignId="CMP1000004385";
createController = function() {
var controller = $controller('assetEditCtrl', {
'$scope': scope
});
return controller;
};
}));
afterEach(function() {
httpBackend.verifyNoOutstandingExpectation();
httpBackend.verifyNoOutstandingRequest();
})
it('should be able to delete an asset', function(){
vm=createController();
assetType="email";
assetName="Untitled";
httpBackend.expectDELETE(baseUrl+'/delete/'+assetId).respond({});
vm.deleteAsset(assetId,assetType,assetName, el);
httpBackend.flush();
});});
Output:
Error: Unsatisfied requests: DELETE ./webresources/assets/delete/EML1000006003 in D:/Tb_test/src/main/webapp/js/libraries/uncompressed/angular-mocks.js
createHttpBackendMock/$httpBackend.verifyNoOutstandingExpectation#D:/Tb_test/src/main/webapp/js/libraries/uncompressed/angular-mocks.js:1488:7
createHttpBackendMock/$httpBackend.flush#D:/Tb_test/src/main/webapp/js/libraries/uncompressed/angular-mocks.js:1467:5
#D:/Tb_test/src/test/js/assetEditCtrlSpec.js:164:3
env.executeFiltered#D:/Tb_test/node_modules/karma-jasmine/lib/boot.js:117:7
createStartFn/<#D:/Tb_test/node_modules/karma-jasmine/lib/adapter.js:171:5
[2]</Karma/this.loaded#http://localhost:9876/karma.js:185:7
Related
I have a simple login controller:
'use strict';
angular.module('login', ['ngRoute'])
.config(['$routeProvider', function ($routeProvider) {
}])
.controller('LoginCtrl', ["$scope", "$route", "LoginService", function ($scope, $route, LoginService) {
var self = this;
this.showGuestLogin = true;
this.showUserLogin = false;
this.toggleUserLoginType = function () {
this.showGuestLogin = !this.showGuestLogin;
this.showUserLogin = !this.showUserLogin;
}
this.submitGuestLogin = function()
{
if(this.guestName === undefined || this.guestName.trim() == '')
{
self.loginError = "Name cannot be blank";
return;
}
LoginService.loginAsGuest(this.guestName.trim())
.then(function()
{
self.loginError = null;
$route.reload();
})
.catch(function(err)
{
self.loginError = 'An error occured. Please try again';
});
}
}]);
I am trying to test it with:
describe('LoginCtrl', function()
{
beforeEach(module('login'));
var ctrl;
beforeEach(inject(function($controller)
{
ctrl = $controller('LoginCtrl');
}));
it('should set error if guest name is undefined', function(done)
{
ctrl.guestName = undefined;
ctrl.submitGuestLogin();
expect(ctrl.loginError).toBeDefined();
});
});
But I am getting this error in console when test runs
Error: [$injector:unpr]
http://errors.angularjs.org/1.5.8/$injector/unpr?p0=%24scopeProvider%20%3C-%20%24scope%20%3C-%20LoginCtrl
I can see in the developer console in the karma driven browser that the controller and it's dependant files are all being loaded correctly.
I can't see what is wrong?
UPDATE
I have tried the suggestions of passing an empty object:
beforeEach(inject(function($controller, $scope, $route, LoginService)
{
ctrl = $controller('LoginCtrl', {
});
}));
and setting up the dependencies:
beforeEach(inject(function($controller, $scope, $route, LoginService)
{
ctrl = $controller('LoginCtrl', {
$scope: $scope,
$route: $route,
LoginService: LoginService
});
}));
Both of which give me this error:
Error: [$injector:unpr]
http://errors.angularjs.org/1.5.8/$injector/unpr?p0=%24scopeProvider%20%3C-%20%24scope
It's because you need to add in the scope in the injection like this:
beforeEach(inject(function($controller, $scope) {
ctrl = $controller('LoginCtrl', { $scope: $scope });
}));
Similarly, if your real controller has injections that you will be using for testing, you'll need to add them in. So for example (and this is only an example):
ctrl = $controller('LoginCtrl',
{
$scope: $scope,
SomeService: SomeService,
moment: moment,
dateFormat: dateFormat
});
Found an answer here which worked: Angular Unit Test Unknown provider: $scopeProvider
beforeEach(inject(function($controller, $rootScope, $route, LoginService)
{
scope = $rootScope.$new();
ctrl = $controller('LoginCtrl', {
$scope: scope
});
}));
In my case I didn't actually need $scope injected into my controller, so I removed it an the original code now works:
beforeEach(inject(function($controller, $rootScope, $route, LoginService)
{
ctrl = $controller('LoginCtrl');
}));
I need to read up on how mocks and injection works!
I am trying to test something pretty simple: a controller that calls a service that performs a http request.
Controller:
define(['module'], function (module) {
'use strict';
var MyController = function ($scope, MyService) {
$scope.testScope = 'karma is working!';
MyService.getData().then(function (data) {
$scope.result = data.hour
});
};
module.exports = ['$scope', 'MyService', MyController ];
});
Test:
define(['require', 'angular-mocks'], function (require) {
'use strict';
var angular = require('angular');
describe("<- MyController Spec ->", function () {
var controller, scope, myService, serviceResponse;
serviceResponse= {
id: 12345,
hour: '12'
};
beforeEach(angular.mock.module('myApp'));
beforeEach(inject(function (_$controller_, _$rootScope_, _MyService_, $q) {
scope = _$rootScope_.$new();
var deferred = $q.defer();
deferred.resolve(serviceResponse);
myService = _MyService_;
spyOn(myService, 'getData').and.returnValue(deferred.promise);
controller = _$controller_('MyController', {$scope: scope});
scope.$apply();
}));
it('should verify that the controller exists ', function() {
expect(controller).toBeDefined();
});
it('should have testScope scope equaling *karma is working*', function() {
expect(scope.testScope ).toEqual('karma is working!');
});
});
});
With the above, i get the error:
TypeError: 'undefined' is not an object (evaluating 'spyOn(myService, 'getData').and.returnValue')
Solved the question - was using Jasmine 1x.. Upgraded to 2.0 and works as expected
I try to write a controller test using karma with jasmine.
I get this error "Error: [$injector:unpr] Unknown SettingsProvider <- settings"
I been stuck for hours googling around but I can't found a solution for this.
My test Case
describe('MyController', function() {
var $scope, controller;
beforeEach(module('MyApp'));
beforeEach(inject(function ($rootScope, $controller) {
$scope = $rootScope.$new();
controller = $controller('MyController', {
$scope: $scope
});
}));
it('sets the options to "valid" if the type is val', function() {
var type = 'val';
$scope.callOptions(type);
expect($scope.options).toBeTruthy();
});
});
My karma.config.js
files: [
'app/bower_components/angular/angular.js',
'app/bower_components/jquery/dist/jquery.min.js',
'app/node_modules/angular-mocks/angular-mocks.js',
'app/bower_components/angular-resource/angular-resource.js',
'app/bower_components/angular-ui-router/release/angular-ui-router.js',
'app/bower_components/angular-ui-router/release/angular-ui-router.min.js',
'app/metronic/assets/global/plugins/angularjs/plugins/angular-ui-router.min.js',
'app/bower_components/ui-router-extras/release/modular/ct-ui-router-extras.sticky.js',
'app/bower_components/ngDraggable/ngDraggable.js',
'app/metronic/assets/global/plugins/angularjs/angular-sanitize.min.js',
'app/metronic/assets/global/plugins/jquery.min.js',
'app/metronic/assets/global/plugins/bootstrap/js/bootstrap.min.js',
'app/metronic/assets/global/plugins/angularjs/plugins/ui-bootstrap-tpls.min.js',
'app/bower_components/ngstorage/ngStorage.min.js',
'app/bower_components/oclazyload/dist/ocLazyLoad.min.js',
'app/metronic/assets/global/plugins/angularjs/plugins/angular-file-upload/angular-file-upload.min.js',
'app/js/services/myProvider.js',
'app/js/app.js',
'app/controllers/MyController.js'
]
My controller :
MetronicApp.controller('MyController',
['$http',
'$rootScope',
'$scope',
'$window',
function ($http, $rootScope, $scope, $window) {
$scope.callOptions = function (type) {
if (type == 'val') {
return $scope.optionsVal;
}
;
if (type == 'Num') {
return $scope.optionsNum;
}
;
};
});
EDIT
I delete some file from my karma.config.js and now I get this error $scope is undefined ..This is a screen shot of the error :
I think the way you injected $rootScope and $controller is incorrect.Please try following code snippet.It will do the thing.
describe('MyController', function() {
var $scope, controller;
beforeEach(module('MyApp'));
beforeEach(inject(function ($injector) {
$scope = $injector.get("$rootScope").$new();
controller = $injector.get("$controller")('MyController', {
$scope: $scope
});
}));
it('sets the options to "valid" if the type is val', function() {
var type = 'val';
$scope.callOptions(type);
expect($scope.options).toBeTruthy();
});
});
I have the following test case MeetingCtrlSpec.js
describe('ViewMeetingCtrl', function () {
var $rootScope, scope, $controller ;
beforeEach(angular.mock.module('MyApp'));
beforeEach(inject(function ($rootScope, $controller ) {
scope = $rootScope.$new();
$controller('ViewMeetingCtrl', {
$scope: scope,
});
}));
it('should change greeting value if name value is changed', function () {
//some assertion
});
});
ViewMeetingCtrl.js
(function () {
'use strict';
angular.module('MyApp').controller('ViewMeetingCtrl', ViewMeetingCtrl);
ViewMeetingCtrl.$inject = ['$scope', '$state', '$http', '$translate', 'notificationService', 'meetingService', '$modal', 'meeting', 'attachmentService'];
function ViewMeetingCtrl($scope, $state, $http, $translate, notificationService, meetingService, $modal, meeting, attachmentService) {
$scope.meeting = meeting;
//more code goes here
}
})();
this meeting comes from the app.routes.js file
.state('company.meeting', {
abstract: true,
url: '/meetings/:meetingId',
template: '<ui-view/>',
resolve: {
meeting: function(meetingService, $stateParams){
return meetingService
.getMeeting($stateParams.meetingId)
.then(function(response){
return response.data;
});
}
},
})
My problem is regarding the injection of meeting in this ctrl . I am not sure how to do inject that in my test case. I did like the following .
describe('ViewMeetingCtrl', function () {
var $rootScope, scope, $controller , meeting ;
beforeEach(angular.mock.module('MyApp'));
beforeEach(inject(function ($rootScope, $controller , meeting ) {
scope = $rootScope.$new();
$controller('ViewMeetingCtrl', {
$scope: scope,
meeting : meeting
});
}));
it('should change greeting value if name value is changed', function () {
//some assertion
});
});
... and i got this error Error: [$injector:unpr] Unknown provider: meetingProvider <- meeting
How do i inject meeting dependency to my test case . ?
Meeting is not a service, but an object that is injected when route is resolve. In you test case you should explicitly create the meeting dummy object.
beforeEach(inject(function ($rootScope, $controller,$q ) {
scope = $rootScope.$new();
$controller('ViewMeetingCtrl', {
$scope: scope,
meeting : {} //your custom object
});
}));
Remember you are testing the controller in your test not the route resolution injection.
I'm trying to test a controller than requires me to mock a service that I'm using to get data. Currently I'm getting an error saying the function is undefined on this line:
dataServiceMock = jasmine.createSpyObj('dataService', ['getFunctionStuff']);
According to other examples and tutorials this should be working fine.
Here's my code including the test file, the service and the controller.
Controller:
var app = angular.module('myApp', []);
app.controller('MainCtrl', function($scope, dataService) {
dataService.getFunctionStuff($scope.foo)
.then(function(data) {
$scope.test = data;
});
});
Service:
app.factory('dataService', function ($timeout, $q){
function getFunctionStuff(formData) {
return $http.post('../randomAPICall', formData).then(function(data) {
return data;
});
};
});
Tests:
describe('Testing a controller', function() {
var $scope, ctrl, $timeout;
var dataServiceMock;
beforeEach(function (){
dataServiceMock = jasmine.createSpyObj('dataService', ['getFunctionStuff']);
module('myApp');
inject(function($rootScope, $controller, $q, _$timeout_) {
$scope = $rootScope.$new();
dataServiceMock.getFunctionStuff.and.ReturnValue($q.when('test'));
$timeout = _$timeout_;
ctrl = $controller('MainCtrl', {
$scope: $scope,
dataService: dataServiceMock
});
});
});
it('should update test', function (){
expect($scope.test).toEqual('test');
});
});
Here's a plunker of it: http://plnkr.co/edit/tBSl88RRhj56h3Oiny6S?p=preview
As you are using jasmine 2.1, the API is .and.returnValue. And in your test spec, do $scope.$apply() before then
describe('Testing a controller', function () {
var $scope, ctrl, $timeout;
var dataServiceMock;
beforeEach(function () {
dataServiceMock = jasmine.createSpyObj('dataService', ['getFunctionStuff']);
module('myApp');
inject(function ($rootScope, $controller, $q, _$timeout_) {
$scope = $rootScope.$new();
dataServiceMock.getFunctionStuff.and.returnValue($q.when('test'));
$timeout = _$timeout_;
ctrl = $controller('MainCtrl', {
$scope: $scope,
dataService: dataServiceMock
});
});
});
it('should update test', function () {
$scope.$apply();
expect($scope.test).toEqual('test');
});
});
Here is another common way to test $http by $httpBackend:
app.js
var app = angular.module('myApp', []);
app.controller('MainCtrl', function($scope, dataService) {
dataService.getFunctionStuff($scope.foo)
.then(function(data) {
$scope.test = data.data;
});
});
dataService.js
app.factory('dataService', function($http) {
function getFunctionStuff(formData) {
return $http.post('../randomAPICall', formData).then(function(data) {
return data;
});
}
return {
getFunctionStuff: getFunctionStuff
};
});
specs.js
describe('Testing a controller', function() {
var $scope, ctrl, $controller, $httpBackend;
beforeEach(function (){
module('myApp');
inject(function($injector) {
$httpBackend = $injector.get('$httpBackend');
$scope = $injector.get('$rootScope').$new();
$controller = $injector.get('$controller');
$scope.foo = 'foo';
$httpBackend.expectPOST('../randomAPICall', 'foo').respond(201, 'test');
ctrl = $controller('MainCtrl', {$scope: $scope});
});
});
it('should update test', function (){
expect($scope.test).not.toBeDefined();
$httpBackend.flush();
expect($scope.test).toEqual('test');
});
});