Skip to content
Search

Vue Test Utils

lastmod 2025-02-14created 2020-10-1619 edits

Vue test utility library.

WARNING

For a simple unit testing method, see the Vue:UnitTest page

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>

Test code:

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 }
  }
}

To simulate the behavior, we first need to locate the button with wrapper.find(), which returns a wrapper for the button element. Then we can simulate the click by calling .trigger() on the button wrapper:

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

A list of APIs frequently used for writing unit test cases.

Shallow Rendering

Test API that tests only the functionality of the component under test, isolating it from child components

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 that also tests the behavior of the child components of the component under test

// 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.
Renders not only the mounted component but also its child components.
shallowMount
Like mount, it creates a Wrapper that contains the mounted and rendered Vue component, but with stubbed child components.
Does not render 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>

When using jest, configure the following in jest.config.js or the jest section of package.json.

// 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

author Zer0 sitemap