How to Test Composable in Vue: Simple Guide with Examples
To test a
composable in Vue, use the renderHook function from @vue/test-utils or create a test component that calls the composable inside its setup function. Then, assert the reactive state or returned values using your test runner like Jest.Syntax
Testing a Vue composable involves calling it inside a test environment and checking its reactive outputs or functions. You can use renderHook from @vue/test-utils or mount a dummy component that uses the composable in its setup().
Key parts:
renderHook(() => useMyComposable()): Runs the composable and returns its reactive state.mount(): Mounts a test component that calls the composable.- Assertions: Use Jest or other test frameworks to check returned values or reactive changes.
javascript
import { renderHook } from '@vue/test-utils' import { ref } from 'vue' function useCounter() { const count = ref(0) function increment() { count.value++ } return { count, increment } } // Usage in test const { result } = renderHook(() => useCounter()) console.log(result.count.value) // 0 result.increment() console.log(result.count.value) // 1
Output
0
1
Example
This example shows how to test a simple useCounter composable that tracks a count and increments it. We use renderHook from @vue/test-utils and Jest assertions to verify behavior.
javascript
import { renderHook } from '@vue/test-utils' import { ref, defineComponent } from 'vue' defineComponent({}) // dummy to avoid errors if needed function useCounter() { const count = ref(0) function increment() { count.value++ } return { count, increment } } test('useCounter increments count', () => { const { result } = renderHook(() => useCounter()) expect(result.count.value).toBe(0) result.increment() expect(result.count.value).toBe(1) })
Output
PASS useCounter increments count
Common Pitfalls
Common mistakes when testing composables include:
- Not wrapping composable calls inside
renderHookor a component'ssetup(), causing errors. - Trying to test composables without waiting for reactive updates or effects.
- Mutating reactive state directly instead of using composable functions.
Always use Vue Test Utils helpers and Jest async utilities if needed.
javascript
/* Wrong way: calling composable directly outside setup or renderHook */ import { ref } from 'vue' function useCounter() { const count = ref(0) function increment() { count.value++ } return { count, increment } } // This will fail because Vue reactivity is not active const counter = useCounter() console.log(counter.count.value) // Might not track reactivity properly /* Right way: use renderHook or mount a component */ import { renderHook } from '@vue/test-utils' const { result } = renderHook(() => useCounter()) console.log(result.count.value) // 0 result.increment() console.log(result.count.value) // 1
Quick Reference
Tips for testing Vue composables:
- Use
renderHookfrom@vue/test-utilsto run composables in isolation. - Alternatively, mount a dummy component that calls the composable in
setup(). - Use Jest or your test runner to assert reactive values and function calls.
- Use
nextTickif you need to wait for reactive updates. - Mock dependencies if your composable uses external APIs or stores.
Key Takeaways
Use renderHook or mount a test component to call the composable inside Vue's reactive context.
Assert reactive state and functions returned by the composable using Jest or your test framework.
Avoid calling composables directly outside setup or renderHook to prevent reactivity issues.
Use nextTick to wait for reactive updates when testing asynchronous composables.
Mock external dependencies to isolate composable behavior in tests.