Vue

Vue Test Utils로 Unit Testing

milliwonkim 2022. 6. 19. 00:02
반응형
SMALL

React에서는 react-dom/test-utils, testing-library/react, enzyme 등 유닛 테스트를 실행할 수 있는 방법이 있습니다.

반면 Vue의 경우, 리액트에서 인기인 testing-library의 Vue 버전인 testing-library/vue가 있긴 하지만, 주로 vue-test-utils를 사용하는 것 같아, vue-test-utils로 적용해보았습니다.

테스트 전, 테스트를 구성을 하도록 하겠습니다.

// jest.config.jsmodule.exports = {
  preset: '@vue/cli-plugin-unit-jest/presets/typescript-and-babel',
  moduleFileExtensions: ['js', 'jsx', 'json', 'vue', 'ts', 'tsx'],
  moduleNameMapper: { '^@/(.*)$': '<rootDir>/src/$1' },
  testMatch: ['**/__tests__/*.[jt]s?(x)'],
  setupFiles: ['<rootDir>/src/tests/setup.ts'],
};
  • setupFiles는 테스트 시, 글로벌하게 적용될 라이브러리 등을 추가할 수 있는 파일을 참조해놓은 속성입니다. 저는 src/tests/setup.ts 파일에서 구성했습니다.
  • moduleFileExtensions는 테스트 파일 작성 시, 사용할 확장자명을 적어두었습니다.
  • testMatch는 테스트를 돌릴 때, 인식할 파일의 위치와 확장자명을 정해두는 곳입니다.

setupFiles에서 지정해놓은 파일에서 테스트 시, ‘@vue/composition-api’를 사용할 수 있도록 구성하도록 하겠습니다.

setup.ts에서 compositionAPI를 Vue.use를 하지 않는다면, 테스트를 돌릴 때 ref, reactive로 정해둔 data를 이용할 수 없어서 테스트가 실패할 것입니다.

// src/tests/setup.ts
import Vue from 'vue';
import compositionAPI from '@vue/composition-api';Vue.use(compositionAPI);

다음은 해당 컴포넌트를 테스트 하도록 하겠습니다.

// src/views/ConsultingPage/ConsultingPage.vue<template>
  <div class="card-view-wrapper">
    <consulting-card-view
      :key="card.id"
      v-for="card in cards"
      :card="card"
    ></consulting-card-view>
  </div>
</template>
<script lang="ts">
import { URL_LISTS } from '@/constants/constants';
import { onMounted, ref } from '@vue/composition-api';
import ConsultingCardView from './ConsultingCardView.vue';
import { IConsultingCard } from '../type';export default {
  components: { 'consulting-card-view': ConsultingCardView },
  setup() {
    const cards = ref<IConsultingCard[]>([]);onMounted(() => {
      cards.value = URL_LISTS;
    });return { cards };
  },
};
</script>

다음은 테스트 파일입니다

// src/views/ConsultingPage/__tests__/ConsultingPage.spec.tsximport { mount } from '@vue/test-utils';
import ConsultingPage from '../ConsultingPage.vue';describe('상담 페이지', () => {
  it('상담 카드가 잘 렌더링 됐는지 확인', () => {
    const cards = [
      {
        image:
          '<https://images.unsplash.com/photo-1438761681033-6461ffad8d80?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1170&q=80>',
        name: '이기원',
        currentJob: '중앙대학교 사회복지학부 3학년',
        mainSection: '학교폭력 상담',
        price: 3000,
        evaluationIndex: 9.0,
      },
    ];    const wrapper = mount(ConsultingPage, {
      data() {
        return { cards };
      },
    });
    console.log(wrapper.html());expect(wrapper.attributes('class')).toBe('card-view-wrapper');
  });
});

mount 시, data를 넣지 않을 경우, ConsultingPage에서 v-for를 하고 있는 consulting-card-view 컴포넌트는 wrapper.html()로 DOM을 볼 경우, mount가 되지 않는 것을 확인할 수 있습니다

  • 테스트에서 mount 시, data를 넣지 않은 경우, 테스트에서 인식하는 ConsultingPage의 DOM
<div class="card-view-wrapper"></div>
  • 테스트에서 mount 시, data를 넣은 경우, 테스트에서 인식하는 ConsultingPage의 DOM
<div class="card-view-wrapper">
  <div class="card-container">
    <div class="card-view-box"><img src="https://images.unsplash.com/photo-1438761681033-6461ffad8d80?ixlib=rb-1.2.1&amp;ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&amp;auto=format&amp;fit=crop&amp;w=1170&amp;q=80" alt="card-view-image" class="card-view-image">
      <div class="teacher-info-box">
        <p class="teacher-name-label">
          이기원 <span class="teacher-label">선생님</span></p>
        <p class="current-job-label">중앙대학교 사회복지학부 3학년</p>
        <div class="section-box">
          <p class="section-label">주요분야</p>
          <p>학교폭력 상담</p>
        </div>
        <div class="price-box">
          <p>3000</p>
          <p>9 / 10.0</p>
        </div>
      </div>
      <v-icon></v-icon>
    </div>
  </div>
</div>
 
반응형
LIST