reactjsreduxredux-sagasaga

How to test redux-saga delay


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 ?


Solution

  • If you check delay saga effect code you can see that it is a bound function:

    export const delay = call.bind(null, delayUtil)
    

    so if you import delay in two different modules it will be two different functions that have no visual difference.

    You can check this in the codesandbox example (see test tab):

    Edit redux-saga delay test

    const testFunction = () => {};
    
    describe("example bound functions equality test", () => {
      it("Two bound functions are not equal", () => {
        expect(testFunction.bind(this))
          .not.toEqual(testFunction.bind(this));
      });
    });
    

    Result is: enter image description here

    To test your saga you should mock your delay effect (if you are using Jest);

    import { delay } from "redux-saga";
    import { incrementAsync } from "../sagas";
    
    jest.mock("redux-saga");
    
    describe("incrementAsync Saga test", () => {
      it("should incrementAsync", () => {
        const generator = incrementAsync();
        expect(generator.next().value).toEqual(delay(1000));
      });
    });