How to Test Vue Component: Simple Guide with Examples
To test a Vue component, use
@vue/test-utils to mount the component and Jest to run assertions on its behavior or output. Write tests that check rendered HTML, component methods, or emitted events to ensure your component works as expected.Syntax
Use mount() from @vue/test-utils to create a wrapper around your component. Then use Jest's expect() to check the output or behavior.
mount(Component): renders the component for testing.wrapper.text(): gets the text content.wrapper.find(selector): finds elements inside the component.expect(value).toBe(expected): asserts expected results.
javascript
import { mount } from '@vue/test-utils' import MyComponent from './MyComponent.vue' test('renders message', () => { const wrapper = mount(MyComponent) expect(wrapper.text()).toContain('Hello') })
Example
This example shows a simple Vue component with a button that increments a counter. The test mounts the component, clicks the button, and checks if the counter updates.
javascript
import { mount } from '@vue/test-utils' import { defineComponent, ref } from 'vue' const Counter = defineComponent({ setup() { const count = ref(0) const increment = () => { count.value++ } return { count, increment } }, template: `<div><button @click=\"increment\">Increment</button><p>Count: {{ count }}</p></div>` }) test('increments count on button click', async () => { const wrapper = mount(Counter) expect(wrapper.text()).toContain('Count: 0') await wrapper.find('button').trigger('click') expect(wrapper.text()).toContain('Count: 1') })
Output
PASS increments count on button click
Common Pitfalls
Not waiting for DOM updates: Vue updates the DOM asynchronously, so use await with events like trigger() to wait for updates.
Testing implementation details: Avoid testing private methods or internal state; test what the user sees or interacts with.
Not cleaning up: Each test should mount fresh components to avoid shared state.
javascript
/* Wrong: missing await causes test to fail */ await wrapper.find('button').trigger('click') // Correct wrapper.find('button').trigger('click') // Wrong /* Wrong: testing internal data directly */ expect(wrapper.vm.count).toBe(1) // Less preferred /* Right: test visible output */ expect(wrapper.text()).toContain('Count: 1')
Quick Reference
| Action | Method | Description |
|---|---|---|
| Mount component | mount(Component) | Render component for testing |
| Find element | wrapper.find(selector) | Select element inside component |
| Get text | wrapper.text() | Get all text content |
| Trigger event | wrapper.find('button').trigger('click') | Simulate user event |
| Assert value | expect(value).toBe(expected) | Check expected result |
Key Takeaways
Use @vue/test-utils mount() to render components for testing.
Always await DOM updates after events with async/await.
Test visible output or emitted events, not internal state.
Write isolated tests to avoid shared component state.
Use Jest expect() assertions to verify component behavior.