Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stubbing API calls and fetch #119

Closed
abelta opened this issue May 18, 2017 · 4 comments
Closed

Stubbing API calls and fetch #119

abelta opened this issue May 18, 2017 · 4 comments

Comments

@abelta
Copy link

abelta commented May 18, 2017

One thing I haven't been able to do successfully with this library is stubbing an API call with fetch to trigger successful or unsuccessful effects, return a specific value, etc.
Things I've tried so far are stubbing with Sinon or passing values with the next method but no results so far.
Can this be done with this library?

@jfairbank
Copy link
Owner

Hi, @abelta!

You should be able to do stubbing/mocking with expectSaga fairly easily.

function* saga() {
  const user = yield call(api.fetchUser);
  yield put({ type: 'DONE', payload: user });
}

// using Jest
it('fetches the user', () => {
  const fakeUser = { id: 1, name: 'Jeremy' };

  return expectSaga(saga)
    .provide([
      [call(api.fetchUser), fakeUser] // <-- catch the call and pass in your own value
    ])
    .put({ type: 'DONE', payload: fakeUser })
    .run();
});

You can check out http://redux-saga-test-plan.jeremyfairbank.com/integration-testing/mocking/static-providers.html and http://redux-saga-test-plan.jeremyfairbank.com/integration-testing/mocking/dynamic-providers.html for some more examples.

If you're using testSaga, there's no reason why you can't inject fake data with the next method.

function* saga() {
  const user = yield call(api.fetchUser);
  yield put({ type: 'DONE', payload: user });
}

it('fetches the user', () => {
  const fakeUser = { id: 1, name: 'Jeremy' };

  testSaga(saga)
    .next()
    .call(api.fetchUser);

    .next(fakeUser) // <-- pass in own value before it's consumed and then used by the put
    .put({ type: 'DONE', payload: fakeUser });
});

Do those examples help?

@abelta
Copy link
Author

abelta commented May 26, 2017

Hey, @jfairbank!
Thank you for your answer but it's still a little confusing to me how to use this to test a saga that might put different actions depending on the circumstances (like call succeeded or failed).
Extending on your example a saga could become something like this:

function* saga() {
  try {
    const user = yield call(api.fetchUser);
    yield put({ type: 'DONE', payload: user });
  } catch (er) {
    yield put({ type: 'FAILED' });
  }
}

Then I like to test it in two runs: one for when it's successful, one for when it fails:

describe('saga', () => {
  describe('call is successful', () => {
    ...
  });
  describe('call is failed', () => {
    ...
  });
});

But this is as far as I get since I'm not yet able to simulate different outcomes from the api call.
What's the recommended way?

@jfairbank
Copy link
Owner

You can simulate thrown errors with providers too: link 1 and link 2.

For your example, it could be something like this.

import { throwError } from 'redux-saga-test-plan/providers';

it('succeeds', () => {
  return expectSaga(saga)
    .provide([
      [call(api.fetchUser), { name: 'Jeremy' }],
    ])
    .put({ type: 'DONE', payload: { name: 'Jeremy' } })
    .run();
});

it('fails', () => {
  return expectSaga(saga)
    .provide([
      [call(api.fetchUser), throwError(new Error('whoops'))],
    ])
    .put({ type: 'FAILED' })
    .run();
});

Please make sure you've read through the docs as they cover most use cases. If you find something lacking in the docs, though, I would greatly appreciate a PR!

@abelta
Copy link
Author

abelta commented Jun 2, 2017

Thank you, @jfairbank. I'll make sure to read the documentation.

@abelta abelta closed this as completed Jun 2, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants