#angularjs #unit-testing #jasmine #karma-jasmine
#angularjs #модульное тестирование #jasmine #карма-jasmine
Вопрос:
Привет, я новичок в AngularJS. Я пытаюсь протестировать службу angular ForumService
. Для этого я должен имитировать ответ, который я получаю при вызове метода service. Я что-то сделал, но я не знаю, правильно это или нет. Я получаю сообщение об ошибке
«ForumService должен использовать сбой функции»
«Ошибка типа: service.getForums не является функцией»
Это сервис, который я тестирую
(function() {
'use strict';
function ForumService($q, $http, config, Forum) {
var service = {};
/**
* Sends a GET request to backend API for all forums.
*
* @return {Promise}
*/
service.getForums = function(onSuccessCallback, onErrorCallback) {
$http.get(config.apiBaseUrl '/api/forums')
.then(
function handleSuccess(response) {
onSuccessCallback(response.data.data);
},
function handleError(response) {
onErrorCallback(response.data.error);
}
);
};
/**
* Sends a GET request to backend API for all forums.
*
* @return {Promise}
*/
service.getForumsPromise = function() {
var q = $q.defer();
$http.get(config.apiBaseUrl '/api/forums')
.then(
function success(response) {
q.resolve(buildForumArray(response.data.data));
},
function error(response) {
q.reject(response.data.error);
}
);
return q.promise;
};
function buildForumArray(data) {
var forumArray = [];
data.forEach(function(forumData) {
forumArray.push(new Forum(forumData));
});
return forumArray;
}
return service;
}
ForumService.$inject = [
'$q',
'$http',
'config',
'Forum'
];
angular
.module('app.services')
.factory('ForumService', ForumService);
})();
Ниже приведен код, в котором я тестирую первый метод service.getForums()
'use strict';
describe('ForumService', function() {
var service, $q, config, httpBackend;
beforeEach(module('app.services'));
beforeEach(module('app.models'));
beforeEach(module(function($provide) {
$provide.service('config', function() {
this.apiBaseUrl = "localhost";
});
$provide.service('ForumService', function() {
this.constructor = jasmine.createSpy('ForumService')
});
$provide.service('Forum', function() {
this.constructor = jasmine.createSpy('Forum')
});
}));
//2.
beforeEach(function() {
inject(function($injector) {
service = $injector.get('ForumService');
httpBackend = $injector.get('$httpBackend');
$q = $injector.get('$q');
});
});
// 5. make sure no expectations were missed in your tests.
afterEach(function() {
httpBackend.verifyNoOutstandingExpectation();
httpBackend.verifyNoOutstandingRequest();
});
it('should use Function', function() {
var returnData = [
{
id: 1,
name: "Programming Questions",
description: "Please post all Questions you have in regards to programming here"
}, {
id: 2,
name: "OOP",
description: "Object Oriented Programming"
}
];
console.info('foo');
httpBackend.when('GET', 'localhost/api/forums').respond(200, returnData);
service.getForums().then(function(response) {
console.info(response); // to see the response
expect(response.data.id).toBe(1);
expect(response.data.name).toBe("Programming Questions");
expect(response.data.description).toBe("Please post all Questions you have in regards to programming here");
});
httpBackend.flush();
});
});
И это мой класс модели
(function() {
'use strict';
angular
.module('app.models')
.factory('Forum', Forum);
Forum.$inject = [];
function Forum() {
/**
* Forum prototype (constructor function).
*
* @param data
* @constructor
*/
function Forum(data) {
var self = this;
if (angular.isDefined(data)) {
self.id = data.id;
self.name = data.name;
self.description = data.description;
} else {
self.id = 0;
self.name = '';
self.description = '';
}
}
return Forum;
}
})();
Ответ №1:
Было много проблем с тестовыми примерами и написанным вами кодом. Исправлены некоторые из них здесь
Прочитайте встроенные комментарии для объяснений
Это должно быть определение вашего getForums
метода:
service.getForums = function(onSuccessCallback, onErrorCallback) {
$http.get(config.apiBaseUrl '/api/forums').then(function handleSuccess(response) {
// You'll get the data inside response.data and not response.data.data
// onSuccessCallback(response.data.data);
onSuccessCallback(response.data);
}, function handleError(response) {
onErrorCallback(response.data.error);
});
};
Если вы действительно хотели вернуть обещание из getForumsPromise
метода, вы могли бы просто сделать это:
service.getForumsPromise = function() {
return $http.get(config.apiBaseUrl '/api/forums');
};
$http.get
promise
в любом случае возвращает a .
И вот как вы должны писать тестовый пример:
'use strict';
describe('ForumService', function() {
var returnData = [{
id: 1,
name: "Programming Questions",
description: "Please post all Questions you have in regards to programming here"
}, {
id: 2,
name: "OOP",
description: "Object Oriented Programming"
}];
//Below line of code is not required.
// var service, $q, config, httpBackend;
beforeEach(module('app.services'));
beforeEach(module('app.models'));
beforeEach(module(function($provide) {
$provide.service('config', function() {
this.apiBaseUrl = "localhost";
});
// Below line of code is not required.
// $provide.service('ForumService', function() {
// this.constructor = jasmine.createSpy('ForumService')
// });
// $provide.service('Forum', function() {
// this.constructor = jasmine.createSpy('Forum')
// });
}));
//2.
// Instead of injecting the services like this
// beforeEach(function() {
// inject(function($injector) {
// service = $injector.get('ForumService');
// httpBackend = $injector.get('$httpBackend');
// $q = $injector.get('$q');
// });
// });
// Inject them like this
beforeEach(inject(function(_ForumService_, _$httpBackend_) {
ForumService = _ForumService_;
$httpBackend = _$httpBackend_;
$httpBackend.when('GET', 'localhost/api/forums').respond(200, returnData);
}))
// 5. make sure no expectations were missed in your tests.
afterEach(function() {
$httpBackend.verifyNoOutstandingExpectation();
$httpBackend.verifyNoOutstandingRequest();
});
it('should use Function', function() {
// This data should be outside a specific it block so that it could be reused.
// Moved it outside.
// var returnData = [{
// id: 1,
// name: "Programming Questions",
// description: "Please post all Questions you have in regards to programming here"
// }, {
// id: 2,
// name: "OOP",
// description: "Object Oriented Programming"
// }];
console.info('foo');
// This should be inside beforeEach block so that it could be reused.
// httpBackend.when('GET', 'localhost/api/forums').respond(200, returnData);
// You call httpBackend's flush right after the call to your service's method and then expect.
// Also your expectations are wrong. So you might get errors.
// Fixing those.
// service.getForums().then(function(response) {
// console.info(response); // to see the response
// expect(response.data.id).toBe(1);
// expect(response.data.name).toBe("Programming Questions");
// expect(response.data.description).toBe("Please post all Questions you have in regards to programming here");
// });
// httpBackend.flush();
// Like this.
var successCallback = function(data) {
expect(data.length).toEqual(2);
expect(data[0].id).toBe(1);
expect(data[0].name).toBe("Programming Questions");
expect(data[0].description).toBe("Please post all Questions you have in regards to programming here");
}
var errorCallback = function(error) {
}
ForumService.getForums(successCallback, errorCallback);
$httpBackend.flush();
});
});
Надеюсь, это поможет