Blog>
Snippets

Testing a Saga with redux-saga-test-plan

Showcase testing a saga by using redux-saga-test-plan library to simulate actions and asserting the effects saga yields.
import { call, put } from 'redux-saga/effects';
import { expectSaga } from 'redux-saga-test-plan';
import { fetchUser } from './api';
import { REQUEST_USER, RECEIVE_USER } from './actions';

// Saga to be testedunction* fetchUserSaga(action) {
  try {
    const user = yield call(fetchUser, action.payload);
    yield put({ type: RECEIVE_USER, user });
  } catch (e) {
    // handle the error within your saga
  }
}
Defines a simple saga for fetching a user which will be the subject of our test.
import { throwError } from 'redux-saga-test-plan/providers';

it('successfully fetches a user', () => {
  const fakeUser = { name: 'John Doe' };
  const userId = 1;

  return expectSaga(fetchUserSaga, { type: REQUEST_USER, payload: userId })
    // Simulate the API call to return `fakeUser`
    .provide([[call(fetchUser, userId), fakeUser]])
    // Assert that the saga will eventually put a RECEIVE_USER action
    .put({ type: RECEIVE_USER, user: fakeUser })
    // Start the test and return the Promise
    .run();
});
Tests the saga to verify it fetches a user correctly by simulating the API call and asserting the output.
it('handles the fetch error', () => {
  const userId = 1;
  const error = new Error('An error occurred');

  return expectSaga(fetchUserSaga, { type: REQUEST_USER, payload: userId })
    // Simulate an error response from the API call
    .provide([
      [call(fetchUser, userId), throwError(error)]
    ])
    // Assert that no RECEIVE_USER action is put due to the error
    // In a real-world scenario, you might check for a specific failure action instead
    // .put({type: 'FETCH_FAILED', error})
    .run();
});
Tests error handling within the saga by simulating an error in the API call.