Vue Test Utils
Vue 테스트 유틸리티 라이브러리.
WARNING |
간단한 유닛 테스트 방법을 확인하고 싶다면 Vue:UnitTest 페이지 참조 |
Categories
- vue
- Vue:UnitTest - 간단한 유닛 테스트.
- Vuetify:UnitTesting - Vuetify 유닛 테스팅.
- vue-i18n-jest - vue i18n, jest, vue test utils 를 조합한 테스트 방법.
- 예제에 vuetify, vue-router 등 조합한 내용이 포함되어 있다.
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.
Installation with Vue CLI (recommended)
If you are using the Vue CLI to build your project, you can use the plugin cli-plugin-unit-jest to run Jest tests.
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.
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
}