title: How do I test component methods on a React component that are defined as arrow functions (class properties)?
body: <p>I am able to test class methods just fine by using spies and <code>Component.prototype</code>. However, many of my class methods are class properties because I need to use <code>this</code> (for <code>this.setState</code>, etc.), and since binding in the constructor is very tedious and looks ugly, using arrow functions is much better in my opinion. The components I have built using class properties work in the browser, so I know my babel config is correct. Below is the component I am trying to test:</p>
  
  <pre><code>    //Chat.js
      import React from 'react';
      import { connect } from 'react-redux';
  
      import { fetchThreadById, passMessageToRedux } from '../actions/social';
      import withLogin from './hoc/withLogin';
      import withTargetUser from './hoc/withTargetUser';
      import withSocket from './hoc/withSocket';
      import ChatMessagesList from './ChatMessagesList';
      import ChatForm from './ChatForm';
  
      export class Chat extends React.Component {
          state = {
              messages : [],
          };
          componentDidMount() {
              const { auth, targetUser, fetchThreadById, passMessageToRedux } = this.props;
              const threadId = this.sortIds(auth._id, targetUser._id);
              //Using the exact same naming scheme for the socket.io rooms as the client-side threads here
              const roomId = threadId;
              fetchThreadById(threadId);
              const socket = this.props.socket;
              socket.on('connect', () =&gt; {
                  console.log(socket.id);
                  socket.emit('join room', roomId);
              });
              socket.on('chat message', message =&gt; passMessageToRedux(message));
              //socket.on('chat message', message =&gt; {
              //    console.log(message);
              //    this.setState(prevState =&gt; ({ messages: [ ...prevState.messages, message ] }));
              //});
          }
  
          sortIds = (a, b) =&gt; (a &lt; b ? `${a}_${b}` : `${b}_${a}`);
  
          render() {
              const { messages, targetUser } = this.props;
              return (
                  &lt;div className='chat'&gt;
                      &lt;h1&gt;Du snakker med {targetUser.social.chatName || targetUser.info.displayName}&lt;/h1&gt;
                      &lt;ChatMessagesList messages={messages} /&gt;
                      &lt;ChatForm socket={this.props.socket} /&gt;
                  &lt;/div&gt;
              );
          }
      }
      const mapStateToProps = ({ chat: { messages } }) =&gt; ({ messages });
  
      const mapDispatchToProps = dispatch =&gt; ({
          fetchThreadById    : id =&gt; dispatch(fetchThreadById(id)),
          passMessageToRedux : message =&gt; dispatch(passMessageToRedux(message)),
      });
  
      export default withLogin(
          withTargetUser(withSocket(connect(mapStateToProps, mapDispatchToProps)(Chat))),
      );
  
      Chat.defaultProps = {
          messages : [],
      };
  </code></pre>
  
  <p>And here is the test file: </p>
  
  <pre><code>//Chat.test.js
  import React from 'react';
  import { shallow } from 'enzyme';
  import { Server, SocketIO } from 'mock-socket';
  
  import { Chat } from '../Chat';
  import users from '../../fixtures/users';
  import chatMessages from '../../fixtures/messages';
  
  let props,
      auth,
      targetUser,
      fetchThreadById,
      passMessageToRedux,
      socket,
      messages,
      wrapper,
      mockServer,
      spy;
  
  beforeEach(() =&gt; {
      window.io = SocketIO;
      mockServer = new Server('http://localhost:5000');
      mockServer.on('connection', server =&gt; {
          mockServer.emit('chat message', chatMessages[0]);
      });
      auth = users[0];
      messages = [ chatMessages[0], chatMessages[1] ];
      targetUser = users[1];
      fetchThreadById = jest.fn();
      passMessageToRedux = jest.fn();
      socket = new io('http://localhost:5000');
      props = {
          mockServer,
          auth,
          messages,
          targetUser,
          fetchThreadById,
          passMessageToRedux,
          socket,
      };
  });
  
  afterEach(() =&gt; {
      mockServer.close();
      jest.clearAllMocks();
  });
  
  test('Chat renders correctly', () =&gt; {
      const wrapper = shallow(&lt;Chat {...props} /&gt;);
      expect(wrapper).toMatchSnapshot();
  });
  
  test('Chat calls fetchThreadById in componentDidMount', () =&gt; {
      const wrapper = shallow(&lt;Chat {...props} /&gt;);
      const getThreadId = (a, b) =&gt; (a &gt; b ? `${b}_${a}` : `${a}_${b}`);
      const threadId = getThreadId(auth._id, targetUser._id);
      expect(fetchThreadById).toHaveBeenLastCalledWith(threadId);
  });
  
  test('Chat calls componentDidMount', () =&gt; {
      spy = jest.spyOn(Chat.prototype, 'componentDidMount');
      const wrapper = shallow(&lt;Chat {...props} /&gt;);
      expect(spy).toHaveBeenCalled();
  });
  
  test('sortIds correctly sorts ids and returns threadId', () =&gt; {
      spy = jest.spyOn(Chat.prototype, 'sortIds');
      const wrapper = shallow(&lt;Chat {...props} /&gt;);
      expect(spy).toHaveBeenCalled();
  });
  </code></pre>
  
  <p>The second to last test which checks if <code>componentDidMount</code>(not a class method) was called runs with no errors, as do all the other tests except the last one. For the last test, Jest gives me the following error:</p>
  
  <pre><code>FAIL  src\components\tests\Chat.test.js
    ● sortIds correctly sorts ids and returns threadId
  
      Cannot spy the sortIds property because it is not a function; undefined given instead
  
        65 |
        66 | test('sortIds correctly sorts ids and returns threadId', () =&gt; {
      &gt; 67 |     spy = jest.spyOn(Chat.prototype, 'sortIds');
        68 |     const wrapper = shallow(&lt;Chat {...props} /&gt;);
        69 |     expect(spy).toHaveBeenCalled();
        70 | });
  
        at ModuleMockerClass.spyOn (node_modules/jest-mock/build/index.js:699:15)
        at Object.&lt;anonymous&gt; (src/components/tests/Chat.test.js:67:16)
  </code></pre>
  
  <p>I have been told that I can use <code>mount</code> from enzyme instead of <code>shallow</code> and then use <code>Chat.instance</code> instead of <code>Chat.prototype</code>, but to my understanding, if I do so, enzyme will also render <code>Chat</code>'s children, and I certainly do not want that. I actually tried using <code>mount</code>, but then Jest started complaining about <code>connect(ChatForm)</code> not having <code>store</code> in either its context or props (<code>ChatForm</code> is connected to redux, but I like to test my redux-connected components by importing the non-connected component and mocking a redux store). Does anyone know how to test class properties on React components with Jest and Enzyme? Thanks a bunch in advance!</p>