TomFree
TomFree

Reputation: 1389

jest spyOn toHaveBeenCalled fail when method is invoked from different object

I try to check for a callback and JEST doesn't notice it being called.

Very simple case to which i drilled it down. Invocation of method Object of class N will call callback object d of class D. It happens - I do see the output, but Jest doesn't recognize it.

I.e. I would expect both Option 1 and Option 2 to result in test passing but in reality only Option 2 succeeds. Seems Jest may be checking for the name being called though documentation on https://jestjs.io/docs/en/jest-object#jestspyonobject-methodname says

Note: By default, jest.spyOn also calls the spied method.

class D{
   callback(id){
      console.log("called with "+id);
   }
}

class N{

   constructor(){
      this.callback = undefined;
   }

   callEm(id){
      this.callback(id);
   }

}
var c = new N();
var d = new D();
c.callback = d.callback;

const spy = jest.spyOn(d, "callback");
c.callEm("crap"); // Option1: leads to test failure but shows print out
//d.callback("crap");// Option2: leads to test success and shows print out

expect(spy).toHaveBeenCalledTimes(1);

Upvotes: 0

Views: 912

Answers (1)

Sanket Phansekar
Sanket Phansekar

Reputation: 741

Changes needed :

  • Spy on D.prototype rather than d
  • Add spy before assigning the callback ie. c.callback=d.callback

class D{
   callback(id){
      console.log("called with "+id);
   }
}

class N{

   constructor(){
      this.callback = undefined;
   }

   callEm(id){
      this.callback(id);
   }

}
var c = new N();
var d = new D();
const spy = jest.spyOn(D.prototype, "callback");
c.callback = d.callback;

c.callEm("crap"); 
d.callback("crap");

expect(spy).toHaveBeenCalledTimes(2);

Update : For this example you can even do const spy = jest.spyOn(d, "callback"); but this works only for that instance of a class.

Upvotes: 3

Related Questions