Hao
Hao

Reputation: 356

Jasmine spyOn function doesn't work in callback

Using spyOn on an object seems to fail if the method is called in a callback function. Any calls to the method in a callback won't be noticed by jasmine.

Please see the code below, I've created a spy on child.print() method. If I call child.print() in a callback (setTimeout), it doesn't work:

it('test', function() {
    const child = {
        print: function() {
            console.log('child');
        }
    };
    spyOn(child, 'print');
    const parent = {
        callChildInCallback: function() {
            setTimeout(()=> child.print(), 1000);
        }
    };
    parent.callChildInCallback();
    expect(child.print.calls.count()).toEqual(1);
});

This one will failed with error "Expected 0 to equal 1."

However if I call it directly, it works:

it('test', function() {
    const child = {
        print: function() {
            console.log('child');
        }
    };
    spyOn(child, 'print');
    const parent = {
        callChild: function() {
            child.print();
        }
    };
    parent.callChild();
    expect(child.print.calls.count()).toEqual(1);
});

I tried to set a breakpoint into the callback, and it seems the spy wrap around the function we're testing is gone, and that's the reason on the surface. Can someone explain why this happen, and the proper way to do it?

Thanks for reading~

Upvotes: 2

Views: 1235

Answers (1)

Winter Soldier
Winter Soldier

Reputation: 2695

You'll need to use jasmine clock to work with timeout functions

it('test', function() {
jasmine.clock().install();
  const child = {
    print: function() {
      console.log('child');
    }
  };
  spyOn(child, 'print').and.callThrough();
  const parent = {
    callChildInCallback: function() {
      setTimeout(function() {
        child.print()
      }, 1000);
    }
  };
  parent.callChildInCallback();
  jasmine.clock().tick(1001);
  expect(child.print.calls.count()).toEqual(1);
});

Upvotes: 3

Related Questions