2. 프로젝트 준비하기

우선, 우리가 테스트를 진행 할 프로젝트가 필요하겠죠. 테스트용 프로젝트를 만드는 시간이 아까우니, 제가 미리 준비해놓은, 이전의 튜토리얼 테스트에서 진행했던 프로젝트에 리덕스를 적용시킨 코드를 사용하여 구현해보겠습니다.

$ git clone https://github.com/vlpt-playground/react-test-tutorial.git
$ git checkout redux-testless

튜토리얼이 진행되기 전에 이전에 프로젝트에서 어떠한 변화가 있었는지 간단하게 짚고 넘어가겠습니다.

  • NameForm, Counter, App 컴포넌트에서 더 이 상 state 를 사용하지 않게 됐습니다.
  • 위에 따라, 해당 컴포넌트들의 테스트 코드들 또한 스냅샷만 찍도록, 수정해주었습니다.
  • API 요청을 통해 받아온 데이터를 보여줄 Post 컴포넌트를 만들었습니다.
  • 리덕스 모듈 세가지: counter, names, post 를 만들었습니다.
  • 리덕스 스토어 생성 할 땐, thunk 미들웨어를 적용해주었습니다.
  • 이에 따른 세가지 컨테이너 컴포넌트: CounterContainer, NamesContainer, PostContainer 가 만들어졌습니다.

우리가, 상태 관련 로직을 리듀서쪽으로 올길 것이기에, 기존에 작성했던 테스트 함수들을 대부분 날려주었습니다.

계속 진행하기전에, 각 리덕스 모듈들이 어떠한 역할을 하는지 알아보겠습니다.

store/modules/counter.js

const INCREASE = 'counter/INCREASE';
const DECREASE = 'counter/DECREASE';

export const increase = () => ({ type: INCREASE });
export const decrease = () => ({ type: DECREASE });

const initialState = {
  number: 0
};

export default function counter(state = initialState, action) {
  switch (action.type) {
    case INCREASE:
      return { number: state.number + 1 };
    case DECREASE:
      return { number: state.number - 1 };
    default:
      return state;
  }
}

단순히, INCREASE, ACTION 액션에 따라 number 값을 더하고, 빼줍니다. 이 모듈에서는, createAction 을 사용하지 않고 액션 생성함수를 직접 작성해주었습니다.

store/modules/names.js

import { createAction, handleActions } from 'redux-actions';

const CHANGE_INPUT = 'names/CHANGE_INPUT';
const INSERT = 'names/INSERT';

export const changeInput = createAction(CHANGE_INPUT, input => input);
export const insert = createAction(INSERT, name => name);

const initialState = {
  input: '',
  names: []
};

export default handleActions({
  [CHANGE_INPUT]: (state, { payload: input }) => ({
    ...state,
    input
  }),
  [INSERT]: (state, { payload: name }) => ({
    ...state,
    names: state.names.concat(name),
  })
}, initialState);

이 모듈에는 두가지 액션이 있습니다. 하나는, 인풋 값을 수정해주는 것이고, 또 하나는 names 배열에 새 아이템을 넣어주는 것 입니다. 불변성을 유지해야 하기에, concat 을 사용해주었습니다.

store/modules/post.js

import { createAction, handleActions } from 'redux-actions';
import axios from 'axios';

function getPostAPI(postId) {
  return axios.get(`http://jsonplaceholder.typicode.com/posts/${postId}`);
}

const GET_POST_PENDING = 'post/GET_POST_PENDING';
const GET_POST_SUCCESS = 'post/GET_POST_SUCCESS';
const GET_POST_FAILURE = 'post/GET_POST_FAILURE';

export const getPost = (postId) => async (dispatch) => {
  dispatch({ type: GET_POST_PENDING });
  try {
    const response = await getPostAPI(postId);
    dispatch({ type: GET_POST_SUCCESS, payload: response });
    return response;
  } catch (e) {
    dispatch({ type: GET_POST_FAILURE, payload: e });
  }
}

const initialState = {
  fetching: false,
  error: false,
  title: '',
  body: '',
};

export default handleActions({
  [GET_POST_PENDING]: (state) => ({ ...state, fetching: true, error: false }),
  [GET_POST_SUCCESS]: (state, { payload: { data } }) => ({ ...state, fetching: false, title: data.title, body: data.body }),
  [GET_POST_FAILURE]: (state) => ({ ...state, fetching: false, error: true })
}, initialState);

비동기 액션을 관리하기 위해서 여러가지 미들웨어들이 있습니다. 그 중 가장 기본적이라고 볼 수 있는 thunk 를 사용하여 jsonplaceholder 에 API 요청을 처리해주었습니다. 우리는 나중에, Post 컴포넌트 내부에 있는 LoadMe 가 적혀있는 버튼을 누르면 이 API 를 요청하고, 화면에 뿌려주도록 하겠습니다.

각 모듈들이 어떤 형식으로 작성하는지 감이 잡히시나요? (잘 모르겠다면, 아마, 리덕스쪽 코드를 조금 복습해야 할 것 같습니다.)

그럼, 슬슬 각 기능들을 위한 테스트 코드를 작성해주겠습니다.

results matching ""

    No results matching ""