How to spy on anonymous function using Jasmine

2019-03-31 04:30发布

问题:

I'm using Jasmine to test my angular application and want to spy on an anonymous function. Using angular-notify service https://github.com/cgross/angular-notify, I want to know whether notify function have been called or not.

Here is my controller:

angular.module('module').controller('MyCtrl', function($scope, MyService, notify) {

  $scope.isValid = function(obj) {
    if (!MyService.isNameValid(obj.name)) {
      notify({ message:'Name not valid', classes: ['alert'] });
      return false;
    }
  }
});

And here is my test:

'use strict';

describe('Test MyCtrl', function () {
  var scope, $location, createController, controller, notify;

  beforeEach(module('module'));

  beforeEach(inject(function ($rootScope, $controller, _$location_, _notify_) {
    $location = _$location_;
    scope = $rootScope.$new();
    notify = _notify_;

    notify = jasmine.createSpy('spy').andReturn('test');

    createController = function() {
      return $controller('MyCtrl', {
        '$scope': scope
      });
    };
  }));

  it('should call notify', function() {
    spyOn(notify);
    controller = createController();
    scope.isValid('name');
    expect(notify).toHaveBeenCalled();
  });
});

An obviously return :

Error: No method name supplied on 'spyOn(notify)'

Because it should be something like spyOn(notify, 'method'), but as it's an anonymous function, it doesn't have any method.

Thanks for your help.

回答1:

Daniel Smink's answer is correct, but note that the syntax has changed for Jasmine 2.0.

notify = jasmine.createSpy().and.callFake(function() {
  return false;
});

I also found it useful to just directly return a response if you only need a simple implementation

notify = jasmine.createSpy().and.returnValue(false);


回答2:

You could chain your spy with andCallFake see:

http://jasmine.github.io/1.3/introduction.html#section-Spies:_andCallFake

    //create a spy and define it to change notify
    notify = jasmine.createSpy().andCallFake(function() {
      return false;
    });

    it('should be a function', function() {
        expect(typeof notify).toBe('function');             
    });

    controller = createController();
    scope.isValid('name');
    expect(notify).toHaveBeenCalled();