Jasmine spyOn on function and returned object

Issue

I’m using MeteorJS with angular and want to test controller. My controller use $reactive(this).attach($scope). I need to check, if this method was called.

I create something like that for spy:

var $reactive = function(ctrl) {
    return {
        attach:function(scope) {}
    }
};

So I can call it like that:

$reactive('aaa').attach('bbb');

How I can do it in tests?

spyOn($reactive, 'attach');

Doesn’t work. I got Error: attach() method does not exist

And how to check if it was called?
This is good call?

expect($reactive).toHaveBeenCalledWith(controller);

And how to check that function attach was called with args (scope)?

Solution

You’ll need to mock the $reactive component. Replace it with a spy that returns an spyObj in the scope of the test. Then trigger what ever makes the $reactive method to run and test.

var reactiveResult = jasmine.createSpyObj('reactiveResult', ['attach']);
var $reactive = jasmine.createSpy('$reactive').and.returnValue(reactiveResult);
var controller = {};
    beforeEach(function () {
      module(function ($provide) {
        $provide.factory('$reactive', $reactive);
      });
      module('yourAppModule');
    });

it('Should call attach', function () {
  $reactive(controller).attach();
  expect($reactive).toHaveBeenCalledWith(controller);
  expect(reactiveResult.attach).toHaveBeenCalled();
}) ;

You can provide the $reactive spy to the controller dependencies too:

var reactiveResult = jasmine.createSpyObj('reactiveResult', ['attach']);
var $reactive = jasmine.createSpy('$reactive').and.returnValue(reactiveResult);
var ctrl;
    beforeEach(inject(function ($controller) {
      ctrl = $controller('YourController', {$reactive: $reactive });
    }));

it('Should call attach', function () {
  //ctrl.triggerThe$reactiveCall
  expect($reactive).toHaveBeenCalledWith(ctrl);
  expect(reactiveResult.attach).toHaveBeenCalled();
}) ;

Answered By – Raulucco

Answer Checked By – Marie Seifert (AngularFixing Admin)

Leave a Reply

Your email address will not be published.