noobprogrammer
noobprogrammer

Reputation: 345

Angular Karma/Jasmine testing: How to mock a service in controller with promises?

I am trying to unit test my controller. The function that I am trying to unit test is:

    function myFunction() {

        MyService
            .myMethod(thing1, thing2)
            .then(function handleMyMethod(result) {
                SomeModule.errorHandler(result)
                    .onSuccess(function onSuccess() {
                        // do stuff
                    })
                    .onError(function onError() {
                        // do stuff
                    });
            });
    }

Relevant test file snippet:

var MockService = {
  myMethod: function(thing1, thing2) {
   var promise = $q.defer().promise;
   return promise;
 }
};

beforeEach(module(function($provide) {
  $provide.value('MyService', MockService);
}));

beforeEach(inject(function (_$controller_, _MyService_, _SomeModule_, ...) {
  ...
  MyService = _MyService_;

  MyController = _$controller_('MyController as Ctrl', {
    $controller: controller,
    MyService: MockService,
  }); 

I am confused about how to write tests that allow me to hit both the onSuccess and onError cases. I am trying to cover both branches for branch coverage, but don't know how the syntax works.

Upvotes: 0

Views: 1711

Answers (1)

Amy Blankenship
Amy Blankenship

Reputation: 6961

You can do it one of two ways:

  1. You can write your mock service to look at the parameters and resolve with an error or success.
    myMethod:function(thing1, thing2) {
        if (thing1=='all good') return $q.when('excellent');
        return $q.reject('sorry, bud');
    }
  1. You can override the method closer to where you're calling it.
it('is a success', function() {
    spyOn(MockService, 'myMethod').and.returnValue($q.when('excellent');
    $rootScope.$apply(
        MyController.doStuff('foo');
    );
    expect(MyController.someProperty).toEqual('excellent');
});
//etc.

Note you don't need to both override the module injector with the provide code and provide the mock service in the $controller locals parameter.

Upvotes: 1

Related Questions