4. 이름 목록 테스팅
이번에는, Names 관련 기능을 위한 테스트 코드를 작성해보겠습니다.
리듀서 작성
아까와 같은 원리로, 리듀서를 위한 테스트 코드를 작성해보겠습니다. 이번에 작성 할 코드의 차이점은, 액션 생성 함수 테스트 부분을 그냥 toMatchSnapshot 을 통하여 비교해주었습니다. 스냅샷은, 꼭 컴포넌트 결과물이 아니여도, 뭐든지 비교 할 수 있습니다. 당연히, 리듀서의 상태 또한 비교하고 싶다면 할 수 있죠.
src/store/modules/names.test.js
import names, * as namesActions from './names';
describe('names', () => {
describe('actions', () => {
const actions = [
namesActions.changeInput('input'),
namesActions.insert('name')
];
it('should create actions', () => {
expect(actions).toMatchSnapshot();
})
});
describe('reducer', () => {
let state = names(undefined, {});
it('should return the initialState', () => {
expect(state).toEqual({
input: '',
names: []
});
});
it('should change input', () => {
state = names(state, namesActions.changeInput('hello'));
expect(state).toHaveProperty('input', 'hello');
});
it('should insert', () => {
state = names(state, namesActions.insert('hello'));
expect(state.names).toEqual(['hello']);
state = names(state, namesActions.insert('world'));
expect(state.names).toEqual(['hello', 'world']);
});
});
});
코드가 아까보다 조금 더 많긴 하지만, 원리는 똑같으니, 새로 보는 코드는 딱히 없지요?
NameForm 테스트 작성하기
이번에는, NameForm 을 위한 테스트 코드를 작성해주겠습니다. 이 또한 이전에 했던 것과 비슷합니다. 클릭 대신 change 와 submit 이벤트를 발생시킬 뿐이죠.
src/components/NameForm.test.js
import React from 'react';
import { shallow } from 'enzyme';
import NameForm from './NameForm';
describe('NameForm', () => {
let component = null;
const mockChange = jest.fn();
const mockSubmit = jest.fn();
it('renders correctly', () => {
component = shallow(
<NameForm
onChange={mockChange}
onSubmit={mockSubmit}
value="hello"
/>
);
});
it('matches snapshot', () => {
expect(component).toMatchSnapshot();
});
it('shows valid input value', () => {
expect(component.find('input').props().value).toBe('hello');
});
it('calls onChange', () => {
const mockedEvent = {
target: {
value: 'world'
}
};
component.find('input').simulate('change', mockedEvent);
expect(mockChange.mock.calls.length).toBe(1);
})
it('calls onSubmit', () => {
component.find('form').simulate('submit');
expect(mockSubmit.mock.calls.length).toBe(1);
});
});
NameList 의 경우엔, 따로 기능이 있진 않으니, 그대로 두셔도 됩니다. 이미 스냅샷 테스팅이 되고있으니까요.
컨테이너 컴포넌트 만들기
이번에는, 한번 통합테스트를 해보겠습니다. 가짜 스토어가 아닌, 실제 스토어릁 넣어서, 액션이 디스패치 되고, 또 상태 값까지 제대로 변경시켜주는지 확인을 해보겠습니다.
src/containers/NameContainer.test.js
import React from 'react';
import { mount } from 'enzyme';
import NamesContainer from './NamesContainer';
import configureStore from '../store/configureStore';
describe('NamesContainer', () => {
let component = null;
let buttons = null;
// 이번엔 실제 store 로 테스팅을 합니다.
let store = configureStore();
const context = { store };
it('renders properly', () => {
component = mount(<NamesContainer />, { context });
});
it('matches snapshot', () => {
expect(component).toMatchSnapshot();
});
it('dispatches CHANGE_INPUT action', () => {
const mockedEvent = {
target: {
value: 'world'
}
};
component.find('input').simulate('change', mockedEvent);
expect(store.getState().names.input).toBe('world');
});
it('dispatches INSERT action', () => {
component.find('form').simulate('submit');
expect(store.getState().names.names).toEqual(['world']);
});
});
NamesContainer 도 테스팅을 모두 마쳤습니다! 유닛 테스트도 잘 되고, 통합 테스트도 잘 되니, 이 컴포넌트는 지금으로선 가히 완벽하다고 볼 수 있겠지요.