0
0
VueHow-ToBeginner · 4 min read

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 renderHook or a component's setup(), 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 renderHook from @vue/test-utils to 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 nextTick if 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.