Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 ?

like image 500
Dimitri Kopriwa Avatar asked Mar 13 '18 18:03

Dimitri Kopriwa


People also ask

How do I test a saga file?

There are two main ways to test Sagas: testing the saga generator function step-by-step or running the full saga and asserting the side effects.

What is redux saga testing?

By Mahesh Jawadi, October 1, 2021. Redux Saga is a middleware library that lets the Redux store interact with resources outside of itself asynchronously. It also handles asynchronous logic in applications. For example, Ajax calls, logging, accessing browsers local storage.

Is redux saga obsolete?

Such a powerful & elegant tool as Redux-Saga, a Redux side effect manager, is said to be deprecated, and no longer being maintained, starting from Jan 27, 2021.

How do you wait in redux saga?

You need to do something - as written this will call sleep (returning a promise) and then immediately throw it away! If you yield a call() then redux-saga will wait for the promise to resolve, e.g.: yield call(sleep, 2) . The best solution is in the answer above - using the delay utility function.


2 Answers

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();
  });
});
like image 142
Fela Maslen Avatar answered Sep 30 '22 21:09

Fela Maslen


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));
  });
});
like image 23
Anton Novik Avatar answered Sep 30 '22 20:09

Anton Novik