title: React Jest Test Fails when setState Called in Promise
body: <p>I'm trying to mock out the a service that returns promises so that I can verify it gets called with the correct parameters.  The way the service is called varies based on the <code>state</code> and the first call to the service sets the <code>state</code>.</p>
  
  <p>When setting the state in the promise it is not updating unless I wrap the assertion in <code>setTimeout</code> or completely stub out the promise.  Is there a way to do this with just a plain promise and an expect?</p>
  
  <p>My component:</p>
  
  <pre><code>class App extends Component {
  
    constructor(props) {
      super(props);
      this.state = {results: []};
      this.service = props.service;
      this.load = this.load.bind(this);
    }
  
    load() {
      if (this.state.results.length === 0) {
        this.service.load('state is empty')
                    .then(result =&gt; this.setState({results: result.data}));
      } else {
        this.service.load('state is nonempty')
                    .then(result =&gt; this.setState({results: result.data}));
      }
    }
  
    render() {
      return (
        &lt;div className="App"&gt;
          &lt;button id="submit" onClick={this.load}/&gt;
        &lt;/div&gt;
      );
    }
  }
  </code></pre>
  
  <p>My test:</p>
  
  <pre><code>it('Calls service differently based on results', () =&gt; {
  
    const mockLoad = jest.fn((text) =&gt; {
      return new Promise((resolve, reject) =&gt; {
        resolve({data: [1, 2]});
      });
    });
  
    const serviceStub = {load: mockLoad};
  
    let component = mount(&lt;App service={serviceStub}/&gt;);
    let button = component.find("#submit");
  
    button.simulate('click');
  
    expect(mockLoad).toBeCalledWith('state is empty');
  
    button.simulate('click');
  
    //this assertion fails as the state has not updated and is still 'state is empty'
    expect(mockLoad).toBeCalledWith('state is nonempty');
  });
  </code></pre>
  
  <p>As mentioned, the following works, but I'd rather not wrap the expect if there's a way around it:</p>
  
  <pre><code>setTimeout(() =&gt; {
      expect(mockLoad).toBeCalledWith('state is nonempty');
      done();
    }, 50);
  </code></pre>
  
  <p>I can also change how I mock the function to stub out the promise which will work:</p>
  
  <pre><code>const mockLoad = jest.fn((text) =&gt; {
    return {
      then: function (callback) {
        return callback({
          data : [1, 2]
        })
      }
    }
  });
  </code></pre>
  
  <p>But I'd like to just return a promise.</p>