Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I am swapping to Jest from Mocha, and I'm wondering if there is a way to spy on a React method. For example, let's say I have the following method in my component (ignore the sdk library, it just constructs a jQuery Ajax call):

getData() {
    sdk.getJSON('/someURL').done(data => {
        this.setState({data});

Using Sinon I would test this by spying on the prototype like so:

it('should call getData', () => {
    sinon.spy(Component.prototype, 'getData');
    mount(<Component />);
    expect(Component.prototype.getData.calledOnce).to.be.true;

This would ensure code coverage without mocking the method. Is there similar functionality in Jest?

EDIT: Also, if this functionality doesn't exist, what is the next best strategy for testing API calls?

Actually you can use jest.spyOn jest.spyOn

If method is called when component created use:

import { mount } from 'enzyme'; 
describe('My component', () => {
  it('should call getData', () => {
    const spy = jest.spyOn(Component.prototype, 'getData');
    mount(<Component />);
    expect(spy).toHaveBeenCalledTimes(1)

or if you have it in your DOM and method use bind you can use:

import { shallow } from 'enzyme'; 
describe('My component', () => {
  it('should call getData', () => {
    const wrapper = shallow(<Component />);
    const instance = wrapper.instance()
    const spy = jest.spyOn(instance, 'getData');
    wrapper.find('button').simulate('click')
    expect(spy).toHaveBeenCalledTimes(1)
                would've been a better answer if you've provided sample usage here, along with your own explanation instead of just posting a link in the answer.
– mxdi9i7
                May 11, 2018 at 19:26
                This answer is even harmful, as it suggests to use the global spyOn which (in my understanding) comes with jasmine-jest2 package to ease migration from jasmine. However, the behaviour seems to be different from jest.spyOn() in that global spyOn (like jasmine's one) doesn't call through by default!
– NicBright
                Feb 20, 2020 at 15:05

You could go for the new spyOn method or the following should also work fine.

it('should call getData', () => {
    Component.prototype.getData = jest.fn(Component.prototype.getData);
    expect(Component.prototype.getData).toBeCalled();

I'm using Jest with React 16.8 - This worked for me:

  it("lifecycle method should have been called", () => {
    jest.spyOn(RedirectingOverlay.prototype, 'componentWillUnmount');
    jest.spyOn(RedirectingOverlay.prototype, 'componentDidMount');
    const wrapper = mount(<RedirectingOverlay message="Hi There!"/>);
    expect(RedirectingOverlay.prototype.componentDidMount).toHaveBeenCalledTimes(1)
    wrapper.unmount()
    expect(RedirectingOverlay.prototype.componentWillUnmount).toHaveBeenCalledTimes(1)

Also using:

  • "enzyme": "^3.6.0"
  • "jest": "23.5.0"
  • "enzyme-adapter-react-16": "^1.5.0"
  • Thanks for contributing an answer to Stack Overflow!

    • Please be sure to answer the question. Provide details and share your research!

    But avoid

    • Asking for help, clarification, or responding to other answers.
    • Making statements based on opinion; back them up with references or personal experience.

    To learn more, see our tips on writing great answers.