2
// Balance.jsx
...

updateToken () {
  const parseResponse = (response) => {
    if (response.ok) {
      return response.json()
    } else {
      throw new Error('Could not retrieve access token.')
    }
  }

  const update = (data) => {
    if (data.token) {
      this.data.accessTokenData = data
    } else {
      throw new Error('Invalid response from token api')
    }
  }

  if (this.props.balanceEndpoint !== null) {
    return fetch(this.props.accessTokenEndpoint, {
      method: 'get',
      credentials: 'include'
    })
    .then(parseResponse)
    .then(update)
    .catch((err) => Promise.reject(err))
  }
}

componentDidMount () {
    this.updateToken()
    .then(() => this.updateBalance())
  }
}

// Test

it('updates the balance', () => {
  subject = mount(<Balance {...props} />)
  expect(fetchMock.called('balance.json')).to.be.true
})

I can't figure out how to test the above using Mocha. The code is does work the method updateBalance is called and the fetch api call actually does happen, but the test still fails. If I call updateBalance() synchronously it passes... How do I tell the test to wait for the promise to resolve?

oligofren
  • 20,744
  • 16
  • 93
  • 180
Riina
  • 530
  • 1
  • 7
  • 19
  • Can you provide `updateToken` code? – Alexandr Lazarev Jun 16 '17 at 09:07
  • Always `return` promises from every function. That way you could easily wait for it. – Bergi Jun 16 '17 at 09:56
  • I've added the updateToken code. I do believe I am returning a promise from the updateToken method as the fetch api returns a promise and i'm directly returning that. I think i have it all setup to work correctly, I just don't know how to get mocha to wait for it... – Riina Jun 16 '17 at 10:39
  • @Riina I think what Bergi meant is that you need to return the promise from `updateToken` to the test function calling it. See me answer below. – oligofren Jun 16 '17 at 12:37

1 Answers1

0

You don't really say what you want to test that the method does, but if all you want to test is that the method resolves on a network call, then there is no need for Sinon or any of that, as this is all you need:

describe("BalanceComponent", () => {
    it("should resolve the promise on a successful network call", () => {
        const component = new BalanceComponent({any: 'props', foo: 'bar'});

        // assumes you call a network service that returns a 
        // successful response of course ...
        return component.updateToken();    
    });
});

This will test that the method actually works, but it is slow and is not a true unit test, as it relies on the network being there and that you run the tests in a browser that can supply you with a working implementation of fetch. It will fail as soon as you run it in Node or if the service is down.

If you want to test that the method actually does something specific, then you would need to to that in a function passed to then in your test:

    it("should change the token on a successful network call", () => {
        const component = new BalanceComponent({any: 'props', foo: 'bar'});
        const oldToken = component.data.accessTokenData;

        return component.updateToken().then( ()=> {
            assert(oldToken !== component.data.accessTokenData);
        });
    });

If you want to learn how to test code like this without being reliant on there being a functioning link to the networked service you are calling, you can check out the three different techniques described in this answer.

oligofren
  • 20,744
  • 16
  • 93
  • 180