Reputation: 14363
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.
How can I test redux-saga delay ?
Upvotes: 14
Views: 18529
Reputation: 102237
If anyone hits the below issue when using the redux-saga-test-plan
package.
instead of writing 'yield call(delay, 600)' where delay is an effect from 'redux-saga/effects' you should write 'yield delay(600)'
You should do this:
saga.ts
:
import { delay } from 'redux-saga/effects';
export function* incrementAsync() {
yield delay(1000);
}
saga.test.ts
:
import { testSaga } from "redux-saga-test-plan"
import { incrementAsync } from "./saga"
describe('incrementAsync', () => {
test('should pass', () => {
testSaga(incrementAsync).next().delay(1000).next().isDone();
})
})
Test result:
PASS redux-saga-examples packages/redux-saga-examples/src/stackoverflow/49263089/saga.test.ts
incrementAsync
✓ should pass (3 ms)
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
saga.ts | 100 | 100 | 100 | 100 |
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 3.208 s
package versions:
"redux-saga-test-plan": "^4.0.1",
"redux-saga": "^1.1.3",
Upvotes: 0
Reputation: 1837
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):
const testFunction = () => {};
describe("example bound functions equality test", () => {
it("Two bound functions are not equal", () => {
expect(testFunction.bind(this))
.not.toEqual(testFunction.bind(this));
});
});
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));
});
});
Upvotes: 10
Reputation: 2162
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();
});
});
Upvotes: 12