Unit testing with takeLatest or takeEvery
See original GitHub issueFrom the examples I’ve seen, if you use a watcher saga that uses takeLatest
or takeEvery
, the tests do not ensure the saga is run after seeing the correct action dispatched.
For example here are my sagas.
function* getDataSaga(action) {
try {
const response = yield call(api.getData, action.payload);
yield put(getDataSucceeded(response));
} catch (e) {
yield put(getDataFailed(e));
}
}
function* watchGetDataSaga() {
yield* takeLatest(GET_DATA, getDataSaga);
}
I could write some tests like this:
describe('My Saga', () => {
it('should first call the getData api', () => {
// arrange
const action = {
type: GET_DATA,
payload: { foo: 'bar' },
};
const iterator = getDataSaga(action);
const expectedYield = call(api.getData, action.payload);
// act
const actualYield = iterator.next().value;
// assert
expect(actualYield).to.deep.equal(expectedYield);
});
});
However, I can’t write tests that make sure the saga is kicked off from a GET_DATA action. It seems to me the only way to do this sort of test is to use a while(true)
in my getDataSaga
instead of having the watchGetDataSaga
. Is this the case, or is there a way around this?
Issue Analytics
- State:
- Created 7 years ago
- Reactions:5
- Comments:18 (6 by maintainers)
Top Results From Across the Web
How to test all effect with redux-saga-test-plan. ...
saga'; import { takeEvery, takeLatest } from '@redux-saga/core/effects'; describe('Unit tests', () => { test('Test all effect', ...
Read more >Saga Helpers · GitBook
Redux Saga Test Plan also offers assertions for the saga helper effects takeEvery , takeLatest , and throttle . These helpers come in...
Read more >Testing side effects using redux saga
In this post I'll try to show you how convenient it is to test side effects ... const { takeEvery, takeLatest } =...
Read more >Testing Sagas
There are two main ways to test Sagas: testing the saga generator function step-by-step or running the full saga and.
Read more >Unit Testing Redux Sagas with Jest | by Gaurav KC
Our sagas being generator functions always yield effects which are saga factory functions like takeEvery, put, call etc. We can test each yield ......
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
Not dumb! I’m no expert myself, but I’ll explain as I understand it.
Both of these basically have the same functional outcome. You can test both in the way we discussed above but the return values are different, so the tests would change.
The
yield*
expression is just a plain JS feature, and it essentially just allows to you toyield
to nested iterables. In this context, doingyield* takeEvery
would mean that you’re yielding to the every value that thetakeEvery
iterable itself yields. So to testyield* takeEvery
, you’d be testing for what valuestakeEvery
itself yields back to you, which means you need to know the internals oftakeEvery
.When using
yield call(takeEvery, ..)
, that’s a declarative effect from redux-saga and it will only everyield
one value and that is aCALL
effect. You can easily test that the correct effect was yielded.So long story short: functionally they are basically the same but testing
call
effects are easier.I made another fiddle that might be more clear: https://jsfiddle.net/npbee/Lqreq12b/2/.
Hope that helps!
call(takeEvery, ...)
is old recommendation, please just usetakeEvery(...)
from theredux-saga/effects
‘subpackage’