How to test redux-saga delay

Dimitri Kopriwa picture Dimitri Kopriwa · Mar 13, 2018 · Viewed 8.8k times · Source

Problem

In redux-saga, I am using yield delay(1000);. During my unit test, I do expect(generator.next().value).toEqual(delay(1000));.

I expect the test to pass.

This is my sagas.js:

import { delay } from 'redux-saga';

export function* incrementAsync() {
  yield delay(1000);
}

This is my sagas.test.js

import { delay } from 'redux-saga';
import { incrementAsync } from '../sagas';

describe('incrementAsync Saga test', () => {
  it('should incrementAsync', () => {
    const generator = incrementAsync();
    expect(generator.next().value).toEqual(delay(1000));
  });
});

● incrementAsync Saga test › should incrementAsync

expect(received).toEqual(expected)

Expected value to equal:
  {"@@redux-saga/CANCEL_PROMISE": [Function anonymous]}
Received:
  {"@@redux-saga/CANCEL_PROMISE": [Function anonymous]}

Difference:

Compared values have no visual difference.

question

How can I test redux-saga delay ?

Answer

Fela Maslen picture Fela Maslen · Oct 13, 2018

A good way to test Redux Saga calls is by using the call effect. In this case, you can slightly refactor your saga as follows:

import { delay } from 'redux-saga';
import { call } from 'redux-saga/effects';

export function* incrementAsync() {
  yield call(delay, 1000);
}

You would then test this like so:

import { delay } from 'redux-saga';
import { call } from 'redux-saga/effects';

describe('incrementAsync', () => {
  it('should incrementAsync()', () => {
    const generator = incrementAsync();

    expect(generator.next().value).toEqual(call(delay, 1000));
  });
});

This works because the result of the yield to call is a simple object, describing a call to the delay function. No need for any mocks :)

There is also of course the great redux-saga-test-plan helper library. Using that, your test would become the following:

import { testSaga } from 'redux-saga-test-plan';
import { delay } from 'redux-saga';
import { call } from 'redux-saga/effects';

describe('incrementAsync', () => {
  it('should incrementAsync()', () => {
    testSaga(incrementAsync)
      .next()
      .call(delay, 1000)
      .next()
      .isDone();
  });
});