스토어에 액션 dispatch 하기

Save 후 스토어에게 fetch 가 성공했다고 알려주는 액션을 dispatch 하려 한다고 가정해봅시다. (실패하는 케이스는 나중에 살펴보겠습니다.)

스토어의 dispatch 함수를 제너레이터에게 넘기면, 제너레이터는 이 함수를 fetch 응답을 받은 후에 실행할것입니다.

// ...

function* fetchProducts(dispatch) {
  const products = yield call(Api.fetch, '/products')
  dispatch({ type: 'PRODUCTS_RECEIVED', products })
}

그러나, 이 방법은 제너레이터 내부에서 함수를 직접적으로 호출하는것과 비슷한 단점이 있습니다 (이전 섹션에서 말했던것 처럼요). 만약 fetchProducts 가 AJAX 응답을 받은 후에 dispatch 를 수행한다는 것을 테스트 하고 싶다면, 또다시 dispatch 함수를 흉내내야 할것입니다.

흉내내는것 대신, 서술적 해결책이 필요합니다. 그저 미들웨어에게 어떤 액션을 dispatch 해야하는지 지시하는 객체를 만들고, 실제 dispatch 는 미들웨어가 하도록 놔두세요. 이렇게만 한다면 yield 된 이펙트를 검사하고 정확한 명령이 포함되어있는지 확인하는 것만으로 제너레이터의 dispatch 를 테스트 할 수 있습니다.

이 라이브러리는 이런 목적들 때문에 dispatch 이펙트를 생성하는 put 함수를 제공합니다

import { call, put } from 'redux-saga/effects'
// ...

function* fetchProducts() {
  const products = yield call(Api.fetch, '/products')
  // dispatch 이펙트를 생성하고 yield 합니다.
  yield put({ type: 'PRODUCTS_RECEIVED', products })
}

자 이제 이전 섹션에서 했던것과 같이 제너레이터를 쉽게 테스트 할 수 있게 되었습니다.

import { call, put } from 'redux-saga/effects'
import Api from '...'

const iterator = fetchProducts()

// expects a call instruction
assert.deepEqual(
  iterator.next().value,
  call(Api.fetch, '/products'),
  "fetchProducts should yield an Effect call(Api.fetch, './products')"
)

// create a fake response
const products = {}

// expects a dispatch instruction
assert.deepEqual(
  iterator.next(products).value,
  put({ type: 'PRODUCTS_RECEIVED', products }),
  "fetchProducts should yield an Effect put({ type: 'PRODUCTS_RECEIVED', products })"
)

next 메소드를 통해 제너레이터에게 어떻게 가짜 응답을 줬는지 기억하세요. 미들웨어 내부가 아니기 때문에 제너레이터를 완벽하게 제어할 수 있고, 이때문에 결과를 흉내내고 제너레이터를 재시작하는것 만으로 실제 환경을 시뮬레이트 할 수 있습니다. 데이터(결과)를 흉내내는것은 함수나 call 들을 흉내내는것보다 훨씬 간단합니다.

results matching ""

    No results matching ""