# Testing Redux Sagas

As much as want to take credit for this post this was mostly written by John Pipkin. It was real good and helped me a lot and I wanted it to be shared with the world.

So testing generators it’s best to think of them as loops that execute when you tell them to.

### Step 1

`it(‘should return 6’, () => { // we’ve set up the generator, but we haven’t called next yet so we’re not at a yield const gen = count()`
`expect(gen.next().value).toEqual(call(addNumber, number, 1))`
`expect(gen.next(1).value).toEqual(call(addNumber, number, 2))`
`expect(gen.next(3).value).toEqual(call(addNumber, number, 3))`
`expect(gen.next(6).value).toEqual(put(something(6)))})`
`function *count() { -> // We haven’t told the generator to exicute anything yet so we’re not at a yield let number = 0`
`number = yield call(addNumber, number, 1) number = yield call(addNumber, number, 2) //3 number = yield call(addNumber, number, 3) //6 yield.put(something(number))}`

In this step we haven’t told the generator to do anything yet, so we don’t have anything to test.

### Step 2

`it(‘should return 6’, () => { const gen = count()`
`// This next is called, we’re seeing what the yield will be expect(gen.next().value).toEqual(call(addNumber, number, 1))`
`expect(gen.next(1).value).toEqual(call(addNumber, number,2))`
`expect(gen.next(3).value).toEqual(call(addNumber, number, 3))`
`expect(gen.next(6).value).toEqual(put(something(6)))})`
`function *count() { let number = 0`
`// Generator is paused here, waiting. The yield call(addNumber, number, 1) hasn’t executed -> number = yield call(addNumber, number, 1) number = yield call(addNumber, number, 2) //3 number = yield call(addNumber, number, 3) //6 yield.put(something(number))}`

Here we’ve executed `gen.next()`. We’ve told the generator to go the yield statement and wait. So now we’re paused at the `->`, but we haven’t actually ran the code.

When we get `gen.next().value` here we’re just getting what the yield WILL do.

### Step 3

`it(‘should return 6’, () => { const gen = count()`
`expect(gen.next().value).toEqual(call(addNumber, number, 1))`
`// called next here, this evaluated the previous line. We pass in the return value from the last line expect(gen.next(1).value).toEqual(call(addNumber, number, 2))`
`expect(gen.next(3).value).toEqual(call(addNumber, number, 3))`
`expect(gen.next(6).value).toEqual(put(something(6)))})`
`function *count() { let number = 0`
`number = yield call(addNumber, number, 1) // We evaluated the previous line, now were waiting at the this yield -> number = yield call(addNumber, number, 2)  number = yield call(addNumber, number, 3) //6 yield.put(something(number))}`

Here we’ve called `gen.next()` again. The generator sees that command and executes the yield that it was paused at and continues the next `yield` statement. It will pause here `->`. `gen.next()` tells the yield statement it was at to execute, we can pass what we want returned from that into the call
We were paused at `yield call(addNumber, number, 1)`, we wanted that to return `1` so we pass that in when we actually execute that line.

### Step 4

`it(‘should return 6’, () => { const gen = count()`
`expect(gen.next().value).toEqual(call(addNumber, number,1))`
`expect(gen.next(1).value).toEqual(call(addNumber, number, 2))`
`// Called next again, we evaluated the call to (number, 2) and specifiy its return value in this next expect(gen.next(3).value).toEqual(call(addNumber, number, 3))`
`expect(gen.next(6).value).toEqual(put(something(6)))})`
`function *count() { let number = 0`
`number = yield call(addNumber, number, 1) number = yield call(addNumber, number, 2) //3 -> number = yield call(addNumber, number,3) //6 yield.put(something(number))}`

This one is just like the previous step, just to illustrate what I’m talking about. The yield to `call(addNumber, number, 2)` should return `3` so we pass that in to the call to `gen.next(3)` because we’ve told the generator to execute that line and we want it to return `3`.

### Step 5

`it(‘should return 6’, () => { const gen = count()`
`expect(gen.next().value).toEqual(call(addNumber, number, 1))`
`expect(gen.next(1).value).toEqual(call(addNumber, number, 2))`
`expect(gen.next(3).value).toEqual(call(addNumber, number, 3))`
`// Called next again, we evaluated the call to (number, 3) and specifiy its return value in this next. // I’ve intentionally returned the wrong value from the call to (addNumber, number, 3) to illustrate how the return in next works expect(gen.next(8).value).toEqual(put(something(8)))})`
`function *count() { let number = 0`
`number = yield call(addNumber, number, 1) number = yield call(addNumber, number, 2) //3 number = yield call(addNumber, number, 3) //6 -> yield.put(something(number))}`

We’ve called `gen.next()` again so now we’re waiting at the yield to put. In this example you can see I intentionally returned the wrong value `8` in `gen.next()`. This is to illustrate that next takes in the return value of the previous execution. Essentailly mock data in this case. Now we see that the yield we’re paused at is the `put(number)`. Since `number` in this case is `8` (because that’s what we told `call(addNumber, number, 3)` to return, that’s what we’re looking for.

### Step 6

`it(‘should return 6’, () => { const gen = count()`
`expect(gen.next().value).toEqual(call(addNumber, number, 1))`
`expect(gen.next(1).value).toEqual(call(addNumber, number, 2))`
`expect(gen.next(3).value).toEqual(call(addNumber, number, 3))`
`expect(gen.next(8).value).toEqual(put(something(8)))`
`// Finally call next again to see there are no more yields expect(gen.next().done).toBeTruthy()})`
`function *count() { let number = 0`
`number = yield call(addNumber, number, 1) number = yield call(addNumber, number, 2) //3 number = yield call(addNumber, number, 3) //6 yield.put(something(number)) ->}`

Finally, we call `gen.next()` again. Since there are no more yields to wait for we can see the saga is done.                Join Hacker Noon