可重用性与组合
大多数
global.mixins
.global.directives
.
测试可组合函数
在使用组合 API 并创建可组合函数时,您通常只想测试可组合函数本身。让我们从一个简单的例子开始
typescript
export function useCounter() {
const counter = ref(0)
function increase() {
counter.value += 1
}
return { counter, increase }
}
在这种情况下,您实际上不需要 @vue/test-utils
。以下是相应的测试
typescript
test('increase counter on call', () => {
const { counter, increase } = useCounter()
expect(counter.value).toBe(0)
increase()
expect(counter.value).toBe(1)
})
对于更复杂的可组合函数,它们使用生命周期钩子(如 onMounted
或 provide
/inject
处理),您可以创建一个简单的测试辅助组件。以下可组合函数在 onMounted
钩子中获取用户数据。
typescript
export function useUser(userId) {
const user = ref()
function fetchUser(id) {
axios.get(`users/${id}`)
.then(response => (user.value = response.data))
}
onMounted(() => fetchUser(userId))
return { user }
}
要测试此可组合函数,您可以在测试中创建一个简单的 TestComponent
。TestComponent
应该以与真实组件完全相同的方式使用可组合函数。
typescript
// Mock API request
jest.spyOn(axios, 'get').mockResolvedValue({ data: { id: 1, name: 'User' } })
test('fetch user on mount', async () => {
const TestComponent = defineComponent({
props: {
// Define props, to test the composable with different input arguments
userId: {
type: Number,
required: true
}
},
setup (props) {
return {
// Call the composable and expose all return values into our
// component instance so we can access them with wrapper.vm
...useUser(props.userId)
}
}
})
const wrapper = mount(TestComponent, {
props: {
userId: 1
}
})
expect(wrapper.vm.user).toBeUndefined()
await flushPromises()
expect(wrapper.vm.user).toEqual({ id: 1, name: 'User' })
})
提供/注入
Vue 提供了一种使用 provide
和 inject
将道具传递给所有子组件的方法。测试此行为的最佳方法是测试整个树(父级 + 子级)。但有时这不可行,因为树过于复杂,或者您只想测试单个可组合函数。
测试 provide
假设您要测试以下组件
vue
<template>
<div>
<slot />
</div>
</template>
<script setup>
provide('my-key', 'some-data')
</script>
在这种情况下,您可以渲染一个实际的子组件并测试 provide
的正确使用,或者您可以创建一个简单的测试辅助组件并将其传递到默认插槽中。
typescript
test('provides correct data', () => {
const TestComponent = defineComponent({
template: '<span id="provide-test">{{value}}</span>',
setup () {
const value = inject('my-key')
return { value }
}
})
const wrapper = mount(ParentComponent, {
slots: {
default: () => h(TestComponent)
}
})
expect(wrapper.find('#provide-test').text()).toBe('some-data')
})
如果您的组件不包含插槽,您可以使用 stub
并用您的测试辅助组件替换子组件
vue
<template>
<div>
<SomeChild />
</div>
</template>
<script setup>
import SomeChild from './SomeChild.vue'
provide('my-key', 'some-data')
</script>
以及测试
typescript
test('provides correct data', () => {
const TestComponent = defineComponent({
template: '<span id="provide-test">{{value}}</span>',
setup () {
const value = inject('my-key')
return { value }
}
})
const wrapper = mount(ParentComponent, {
global: {
stubs: {
SomeChild: TestComponent
}
}
})
expect(wrapper.find('#provide-test').text()).toBe('some-data')
})
测试 inject
当您的组件使用 inject
并且您需要使用 provide
传递数据时,您可以使用 global.provide
选项。
vue
<template>
<div>
{{ value }}
</div>
</template>
<script setup>
const value = inject('my-key')
</script>
单元测试可能看起来像这样
typescript
test('renders correct data', () => {
const wrapper = mount(MyComponent, {
global: {
provide: {
'my-key': 'some-data'
}
}
})
expect(wrapper.text()).toBe('some-data')
})
结论
- 测试简单的可组合函数,无需组件和
@vue/test-utils
- 创建一个测试辅助组件来测试更复杂的可组合函数
- 创建一个测试辅助组件来测试您的组件是否使用
provide
提供了正确的数据 - 使用
global.provide
将数据传递给使用inject
的组件