user1024941 user1024941 - 1 year ago 160
AngularJS Question

Karma testing controller that calls service with http

Can someone please tell me the best way to run tests on my controller function getData and the factory function too. I've very confused and don't know where to start. How would you write tests for the code below?

myApp.controller('myController', ['$scope', 'myFactory', function ($scope, myFactory) {

$scope.getData = function(id) {
var promise = myFactory.GetData('/dta/GetData?Id=' + id);
.then(function (success) {
$scope.result = success;
}, function (error) {
$scope.error = true;

myApp.factory('myFactory', ['$http', function ($http) {
return {
GetData: function (url) {
return $http.get(url)
.then(function (response) {
}, function (error) {
return error;

Answer Source

You'll want to test each component in isolation (that's what unit tests are for). So something like this for the controller

describe('myController test', () => {
    let scope, myFactory;

    beforeEach(() => {
        myFactory = jasmine.createSpyObj('myFactory', ['GetData']);            

        inject(function($rootScope, $controller) {
            scope = $rootScope.$new();

            $controller('myController', {
                $scope: scope,
                myFactory: myfactory

    it('getData assigns result on success', inject(function($q) {
        let id = 1, success = 'success';

        expect(myFactory.GetData).toHaveBeenCalledWith('/dta/GetData?Id=' + id);
        scope.$digest(); // resolve promises

    it('getData assigns error on rejections', inject(function($q) {


For your factory, you would create a separate describe and inject and configure $httpBackend. There are plenty of example in the documentation.

FYI, you should omit the error handler in your factory, ie

return $http.get(url).then(response =>;

as you are currently converting a failed request into a successful promise.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download