2016-12-24 3 views
2

私は、APIの呼び出しを行い、結果を処理し、次のReduxの佐賀、持っている:私はすべてがこれらの冗談で動作するかどうかをテストしていは、手動発電機に値を渡すと、冗談テストで予期しない結果が得られ

import { takeLatest } from 'redux-saga' 
import { call, put } from 'redux-saga/effects' 
import { normalize, arrayOf } from 'normalizr' 
import * as actions from './actions' 
import * as schemas from './schemas' 
import * as types from './actionTypes' 
import { api, constants as apiConstants } from '../../services/api' 

export function* fetchWorks() { 
    const { response, error } = yield call(api.getJson, apiConstants.WORKS_ENDPOINT) 
    if (response) { 
    const normalized = normalize(response.items, arrayOf(schemas.works)) 
    yield put(actions.fetchWorksSuccess(normalized)) 
    } else { 
    yield put(actions.fetchWorksFail(error)) 
    } 
} 

を試験は:

import { takeLatest } from 'redux-saga' 
import { call, put } from 'redux-saga/effects' 
import * as sagas from './sagas' 
import * as actions from './actions' 
import * as types from './actionTypes' 
import { api, constants as apiConstants } from '../../services/api' 

describe('works saga',() => { 
    describe('fetchWorks',() => { 
    it('should fetch data',() => { 
     const generator = sagas.fetchWorks() 
     const actual = generator.next().value 
     const expected = call(api.getJson, apiConstants.WORKS_ENDPOINT) 
     expect(actual).toEqual(expected) 
    }) 

    // this test requires me to pass a response object to the generator 
    it('should put fetchWorksSuccess on a response',() => { 
     // so I create it here 
     const response = { 
     items: [{ 
      sys: { id: '1' }, 
      fields: { content: 'content' } 
     }] 
     } 
     const generator = sagas.fetchWorks() 
     const expected = put(actions.fetchWorksSuccess()) 
     // but I would expect to pass it here  
     generator.next() 
     // but actually the test only succeeds if I pass it here 
     const actual = generator.next({ response }).value 
     expect(actual).toEqual(expected) 
    }) 

    // same goes for this test 
    it('should put fetchWorksFail on errors',() => { 
     const error = new Error('Something went wrong') 
     const generator = sagas.fetchWorks() 
     const expected = put(actions.fetchWorksFail()) 
     generator.next() 
     const actual = generator.next({ error }).value 
     expect(actual).toEqual(expected) 
    }) 
    }) 
}) 

しかし、'should put fetchWorksSuccess on a response''should put fetchWorksFail on errors'試験のため、私は手動でそれぞれ発電機に{response}{error}オブジェクトを通過しなければなりません。

私はこれらのオブジェクトが必要であることを理解しています(応答があるかどうかを調べるif文のため)。なぜ最初の代わりに2番目の.next()に渡す必要があるのか​​分かりません。私がそれを見る方法では、最初のyieldは応答またはエラーオブジェクトであり、2番目のものではありません。なぜ誰かが理解していますか?

答えて

1

これはリアクションのものではなく、ジェネレータのものです。

>>> function *example_generator() { 
    console.log('before first yield', Array.slice(arguments)); 
    var first_yield = yield 'first'; 
    console.log('first yield returned', first_yield); 
    var second_yield = yield 'second'; 
    console.log('second yield returned', second_yield); 
    return 'done'; 
} 
>>> generator = example_generator("generator", "creation") 
Generator {} 
>>> generator.next("first next") 
before first yield Array [ "generator", "creation" ] 
Object { value: "first", done: false } 
>>> generator.next("second next") 
first yield returned second next 
Object { value: "second", done: false } 
>>> generator.next("third next") 
second yield returned third next 
Object { value: "done", done: true } 

fetchWorks()へのあなたの最初の呼び出しはジェネレータオブジェクトを作成しますが、実際に発電を開始しません:generator.next()

最初の呼び出しは、歩留まりの呼び出しからの戻りは、発電機を起動していません。

このように考えると、next()の最初の呼び出しでは、最初のyieldに渡される値が与えられます。 2番目の呼び出しでnext()を指定すると、最初のyieldの戻り値を指定できます。

+0

ありがとうございます。 MDNのドキュメントは、私がそれを理解するのに本当に役立たなかった。この記事(https://davidwalsh.name/es6-generators)とcodepen(https://codepen.io/anon/pen/GNbRpe?editors=0010)を試してみると、私の理解に役立ちました。ありがとう! –

関連する問題