Testing Composables
If a composable only uses Reactivity APIs, then it
can be tested by directly invoking it and
asserting its returned state / methods:
// counter.js
import { ref } from 'vue'
export function useCounter() {
const count = ref(0)
const increment = () => count.value++
return {
count,
increment
}
}
// counter.test.js
import { useCounter } from './counter.js'
test('useCounter', () => {
const { count, increment } = useCounter()
expect(count.value).toBe(0)
increment()
expect(count.value).toBe(1)
})
A composable that relies on lifecycle hooks or
Provide / Inject needs to be wrapped in a host
component to be tested. We can create a helper
like the following:
// test-utils.js
import { createApp } from 'vue'
export function withSetup(composable) {
let result
const app = createApp({
setup() {
result = composable()
// suppress missing template warning
return () => {}
}
})
app.mount(document.createElement('div'))
// return the result and the app instance
// for testing provide / unmount
return [result, app]
}
import { withSetup } from './test-utils'
import { useFoo } from './foo'
test('useFoo', () => {
const [result, app] = withSetup(() => useFoo(123))
// mock provide for testing injections
app.provide(...)
// run assertions
expect(result.foo.value).toBe(1)
// trigger onUnmounted hook if needed
app.unmount()
})