Skip to content

Vue Test Utils

Vue 테스트 유틸리티 라이브러리.

WARNING

간단한 유닛 테스트 방법을 확인하고 싶다면 Vue:UnitTest 페이지 참조

Categories

Introduce

Unit testing is a fundamental part of software development. Unit tests execute the smallest units of code in isolation, in order to increase ease of adding new features and track down bugs. Vue’s single-file components make it straight forward to write unit tests for components in isolation. This lets you develop new features with confidence you are not breaking existing ones, and helps other developers understand what your component does.

If you are using the Vue CLI to build your project, you can use the plugin cli-plugin-unit-jest to run Jest tests.

$ vue add unit-jest

The plugin pulls all required dependencies (including jest), creates a jest.config.js file with sensible defaults, and generates a sample test suite.

After that, all you need to do is to install Vue Test Utils.

$ npm install --save-dev @vue/test-utils

Simple example

// Import the `mount()` method from Vue Test Utils
import { mount } from '@vue/test-utils'

// The component to test
const MessageComponent = {
  template: '<p>{{ msg }}</p>',
  props: ['msg']
}

test('displays message', () => {
  // mount() returns a wrapped Vue component we can interact with
  const wrapper = mount(MessageComponent, {
    propsData: {
      msg: 'Hello world'
    }
  })

  // Assert the rendered text of the component
  expect(wrapper.text()).toContain('Hello world')
})

Base Example

This simple example tests whether some text is rendered:

<template>
  <div>
    <input v-model="username">
    <div
      v-if="error"
      class="error"
    >
      {{ error }}
    </div>
  </div>
</template>

<script>
export default {
  name: 'Hello',
  data () {
    return {
      username: ''
    }
  },

  computed: {
    error () {
      return this.username.trim().length < 7
        ? 'Please enter a longer username'
        : ''
    }
  }
}
</script>

테스트 코드:

import { shallowMount } from '@vue/test-utils'
import Hello from './Hello.vue'

test('Hello', () => {
  // render the component
  const wrapper = shallowMount(Hello)

  // should not allow for `username` less than 7 characters, excludes whitespace
  wrapper.setData({ username: ' '.repeat(7) })

  // assert the error is rendered
  expect(wrapper.find('.error').exists()).toBe(true)

  // update the name to be long enough
  wrapper.setData({ username: 'Lachlan' })

  // assert the error has gone away
  expect(wrapper.find('.error').exists()).toBe(false)
})

The above code snippet shows how to test whether an error message is rendered based on the length of the username. It demonstrates the general idea of unit testing Vue components: render the component, and assert that the markup matches the state of the component.

Simulating User Interaction

Let's imagine a counter component that increments when user clicks the button:

const Counter = {
  template: `
    <div>
      <button @click="count++">Add up</button>
      <p>Total clicks: {{ count }}</p>
    </div>
  `,
  data() {
    return { count: 0 }
  }
}

동작을 시뮬레이션하려면 먼저 버튼 요소에 대한 래퍼를 반환하는 wrapper.find()로 버튼을 찾아야합니다. 그런 다음 버튼 래퍼에서 .trigger()를 호출하여 클릭을 시뮬레이션 할 수 있습니다:

test('increments counter value on click', async () => {
  const wrapper = mount(Counter)
  const button = wrapper.find('button')
  const text = wrapper.find('p')

  expect(text.text()).toContain('Total clicks: 0')

  await button.trigger('click')

  expect(text.text()).toContain('Total clicks: 1')
})

Notice how the test must be async and that trigger needs to be awaited. Check out the Testing Asynchronous Behavior guide to understand why this is needed and other things to consider when testing asynchronous scenarios.

APIs

단위 테스트 케이스 작성을 위해 자주 사용하는 API 목록입니다.

Shallow Rendering

테스트 할 컴포넌트의 기능만 테스트하고 하위 컴포넌트와는 분리해주는 테스트 API

import { shallowMount } from '@vue/test-utils'
import Component from './component'

describe('Component', () => {
  test('is a Vue instance', () => {
    const wrapper = shallowMount(Component);
    expect(wrapper.isVueInstance()).toBeTruthy();
  })
})

Mount

테스트할 컴포넌트의 하위 컴포넌트의 동작까지 함께 테스트 하는 API

// helloworld.test.js
import { mount } from '@vue/test-utils';
import HelloWorld from './HelloWorld.vue';

test('HelloWorld Component', () => {
  const wrapper = mount(HelloWorld);
  expect(wrapper.vm.message).toBe('Vue!');
});

mount vs shallowMount

mount
Creates a Wrapper that contains the mounted and rendered Vue component.
mount 한 컴포넌트 뿐만 아닌, 자식 컴포넌트 까지 렌더링 한다.
shallowMount
Like mount, it creates a Wrapper that contains the mounted and rendered Vue component, but with stubbed child components.
자식 컴포넌트들을 렌더링 하지 않는다.

Troubleshooting

Unknown custom element: <v-app-bar> - did you register the component correctly?

/usr/bin/node --require /home/your/Applications/pycharm/plugins/JavaScriptLanguage/helpers/jest-intellij/lib/jest-intellij-stdin-fix.js /home/your/Project/answer-dev/fe/node_modules/@vue/cli-service/bin/vue-cli-service.js test:unit --colors --reporters /home/your/Applications/pycharm/plugins/JavaScriptLanguage/helpers/jest-intellij/lib/jest-intellij-reporter.js --verbose "--testNamePattern=^HelloWorld\.vue " --runTestsByPath /home/your/Project/answer-dev/fe/tests/unit/components/AppBarTitle.spec.ts
  console.error node_modules/vue/dist/vue.runtime.common.dev.js:621
    [Vue warn]: Unknown custom element: <v-app-bar> - did you register the component correctly? For recursive components, make sure to provide the "name" option.

    found in

    ---> <AppBarTitle>
           <Root>

jest를 사용할 경우, jest.config.js 또는 package.json의 jest 영역에 다음과 같이 설정한다.

// file: jest.config.js
module.exports = {
  // ... 
  setupFiles: ['./tests/setup.js'], // <- add this
}
// file: ./tests/setup.js
import Vue from 'vue'
import Vuetify from 'vuetify'

Vue.use(Vuetify)

Favorite site