15

I am very new to this (angularjs, jasmine, testacular) and I have this code (I simplified it a bit, leaving only what matters):

//my_module.js
angular.module('my_module', ['my_data'])
.config([...]);

.controller('my_controller', ['$scope', 'my_data',
    function($scope, my_data) {
        $scope.my_function = function() {
            return my_data.my_factory.save().then(function () {
                console.log('saved');
            },
            function() {                             
                console.log('Error');
            }); 
        }
    }
)

//my_data.js
angular.module('my_data', [])
.factory('my_factory', ['$q', '$rootScope',
    function($q, $rootScope) {
        var my_factory= function(my_data) {
            angular.extend(this, my_data);
        }
        my_factory.prototype.save = function() {
            var deferred = $q.defer();
            setTimeout(function() {
                deferred.resolve();
            $rootScope.$apply();
            }, 1000);

            return deferred.promise;
        }
        return my_factory;
    }
])

So, what I want to do is to test if my_data.my_factory.save is called when the my_module.my_controller.my_function is fired.

//my_test.js
describe('testing my_controller.my_function', function () {
    beforeEach(module('my_module'));

    var $rootScope, $controller;
    beforeEach(inject(function(_$rootScope_, _$controller_) {
        $rootScope = _$rootScope_;
        $controller = _$controller_;
    }));

    scope = $rootScope.$new();

    it('should call the save function', function() {
        scope.my_function();
        expect(my_data.save).toHaveBeenCalled();
    });
}

I need a little bit of help.

1 Answer 1

25

You're not too far from what you need. First off, as you require my_data as my_module dependency, you don't need to inject my_module to the controller, just the factory (my_factory);

Secondly, you want to make use of ngMock. The docs are not very complete, but give a good insight. More here and a example here (look for test/unit/controllers).

Basically, what you want to do is to mock the service so you can be assured it has been called. To achieve it, inject $provide to your angular.mock.module call and provide a mocked my_factory service. The best way to achieve it is something like this:

describe('testing my_controller.my_function', function () {
  var mockedFactory, $rootScope, $controller;

  beforeEach(module('my_module', function($provide) {
    mockedFactory = {
      save: jasmine.createSpy()
    };

    $provide.value('my_factory', mockedFactory);
  }));

  beforeEach(inject(function(_$rootScope_, _$controller_) {
    $rootScope = _$rootScope_;
    $controller = _$controller_;
  }));

  scope = $rootScope.$new();

  it('should call the save function', function() {
    scope.my_function();
    expect(mockedFactory.save).toHaveBeenCalled();
  });
}

This way you'll override my_factory dependency.

Sign up to request clarification or add additional context in comments.

1 Comment

Hi @CaioCunha.. Which controller you are testing? Where you specify it? I really liked this approach, and I am refactoring same of my test but I got this doubt github.com/Ridermansb/listfy/blob/feature/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.