redux-saga で、yield call
の戻り値の処理をしたあと、次の yield 式を呼び出すときのテストコードについて検討しました。単純化したコードはこうです。API呼び出しのアクションを実行したあと、_SUCCESS アクションを実行するパターンです。
export function* targetSaga() {
const response = yield call(callApi)
const foo = response.foo
yield put(barActionCreator(foo))
}
ここで yield put
のテストを開始するにはどうすればよいでしょうか。
引数つきでnext() を呼ぶとジェネレーター関数の実行が再開され、処理が停止していた yield 式を next() の引数で置き換えます。挙動を確認しましょう。
% node
> function* generator() {
... const one = yield '1'
... console.log('one', one)
... const two = yield '2'
... console.log('two', two)
... const three = yield '3'
... console.log('three', 'three')
... }
undefined
>
> gen = generator()
{}
>
> gen.next('aaa')
{ value: '1', done: false }
> gen.next('bbb')
one bbb
{ value: '2', done: false }
gen.next('aaa')
では、「処理が停止していた yield 式」がまだないので、'aaa' はどこにも反映されません。
gen.next('bbb')
では、「処理が停止していた yield 式」は const one = yield '1'
です。この yield 式である yield '1'
が 'bbb' に置き換わります。つまり、const one = 'bbb'
となります。その結果次の console.log('one', one)
が one bbb
を出力しています。
この機能は次のようにテストコードで利用できます。
import { put, call } from 'redux-saga/effects'
import { cloneableGenerator } from 'redux-saga/utils'
const barAction = barActionCreator()
const generator = cloneableGenerator(targetSaga)(barAction)
const clone = generator.clone() // ここまでは準備
expect(clone.next().value).toEqual(call(callApi, { editingId }))
const foo = {
// something
}
expect(clone.next(foo).value).toEqual(put(barActionCreator(...
「処理が停止していた」 yield call
の戻り値を next の引数で差し替えたうえで、次の yield 式である、yield put(barActionCreator...
が実行されます。