DEV Community

Chris Cook
Chris Cook

Posted on • Edited on • Originally published at zirkelc.dev

How To Spy on Classes

Spying in Jest allows us to mock classes while keeping the original implementation intact. A spy can help us verify if a certain method was invoked, without interfering with its functionality. However, the process of spying can vary, especially when dealing with class methods versus simple functions. There are three main scenarios we need to deal with: spying on static methods, spying on methods of a single instance, and spying on methods of all instances of a class.

Spying on Static Methods

Static methods are associated with the class itself, not with any specific instance of the class. This makes spying on them relatively straightforward. We simply reference the class and specify which static method we want to spy on.

class Person {
  static hello() {
    return 'Hello, I am a static method.';
  }

  goodbye() {
    return 'Goodbye, I am an instance method.';
  }
}
test('should call static method', () => {
  // Spy on the static method
  const spy = jest.spyOn(Person, 'hello');

  // Invoke the static method
  Person.hello();

  // Test if the static method has been called
  expect(spy).toHaveBeenCalled();
});
Enter fullscreen mode Exit fullscreen mode

Spying on Methods of a Single Instance

In scenarios where we have access to a particular instance of the class, we can set a spy on any of this instance's methods. We simply reference the instance and the method we want to spy on.

class Person {
  static hello() {
    return 'Hello, I am a static method.';
  }

  goodbye() {
    return 'Goodbye, I am an instance method.';
  }
}

test('should call instance method of single object', () => {
  // Create an instance of the class
  const person = new Person();

  // Spy on the instance method
  const spy = jest.spyOn(person, 'goodbye');

  // Invoke the method on the instance
  person.goodbye();

  // Test if the method on the instance has been called
  expect(spy).toHaveBeenCalled();
});
Enter fullscreen mode Exit fullscreen mode

Spying on Methods of All Instances

In many real-world cases, we may not have access to the specific instance of the class we want to spy on. This instance might be hidden in a module we are testing and not directly exported or accessible from our test case. In such situations, we may choose to spy on all instances of a class. To do this, we reference the prototype of the class and the method we want to spy.

class Person {
  static hello() {
    return 'Hello, I am a static method.';
  }

  goodbye() {
    return 'Goodbye, I am an instance method.';
  }
}

// Create an instance and call the instance method
function goodbye() {
  const person = new Person();
  return person.goodbye();
}

test('should call instance method of all objects', () => {
  // Spy on the instance method for all instances
  const spy = jest.spyOn(Person.prototype, 'goodbye');

  // Call function without access to underlying instance
  goodbye();
  goodbye();

  // Test if the method has been called on any instance
  expect(spy).toHaveBeenCalledTimes(2);
});
Enter fullscreen mode Exit fullscreen mode

I hope you found this post helpful. If you have any questions or comments, feel free to leave them below. If you'd like to connect with me, you can find me on LinkedIn or GitHub. Thanks for reading!

Top comments (3)

Collapse
 
danielepecora profile image
Daniele Pecora

nice follow up!

Collapse
 
zirkelc profile image
Chris Cook

I’m glad you like it! :)

Collapse
 
niklampe profile image
Nik

Love your posts. So helpful!