Appearance
可重用性和组合
¥Reusability & Composition
大多:
¥Mostly:
global.mixins
。global.directives
。
测试可组合项
¥Testing composables
使用组合 API 并创建可组合项时,你通常只想测试可组合项。让我们从一个简单的例子开始:
¥When working with the composition API and creating composables, you often want to test only the composable. Let's start with a simple example:
typescript
export function useCounter() {
const counter = ref(0)
function increase() {
counter.value += 1
}
return { counter, increase }
}
在这种情况下,你实际上并不需要 @vue/test-utils
。这是相应的测试:
¥In this case, you don't actually need @vue/test-utils
. Here is the corresponding test:
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
钩子中获取用户数据。
¥For more complex composables, which use lifecycle hooks like onMounted
or provide
/inject
handling, you can create a simple test helper component. The following composable fetches the user data within the onMounted
hook.
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
使用可组合项的方式应该与真实组件使用它的方式完全相同。
¥To test this composable, you can create a simple TestComponent
within the tests. The TestComponent
should use the composable the exact same way how the real components would use it.
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' })
})
提供/注入
¥Provide / inject
Vue 提供了一种通过 provide
和 inject
将 props 传递给所有子组件的方法。测试此行为的最佳方法是测试整个树(父树+子树)。但有时这是不可能的,因为树太复杂,或者你只想测试单个可组合项。
¥Vue offers a way to pass props to all child components with provide
and inject
. The best way to test this behavior is to test the entire tree (parent + children). But sometimes this is not possible, because the tree is too complex, or you only want to test a single composable.
测试 provide
¥Testing provide
我们假设你要测试以下组件:
¥Let's assume the following component you want to test:
vue
<template>
<div>
<slot />
</div>
</template>
<script setup>
provide('my-key', 'some-data')
</script>
在这种情况下,你可以渲染一个实际的子组件并测试 provide
的正确用法,也可以创建一个简单的测试辅助组件并将其传递到默认插槽中。
¥In this case you could either render an actual child component and test the correct usage of provide
or you can create a simple test helper component and pass it into the default slot.
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
并用测试助手替换子组件:
¥If your component does not contain a slot you can use a stub
and replace a child component with your test helper:
vue
<template>
<div>
<SomeChild />
</div>
</template>
<script setup>
import SomeChild from './SomeChild.vue'
provide('my-key', 'some-data')
</script>
和测试:
¥And the test:
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
¥Testing inject
当你的组件使用 inject
并且你需要用 provide
传递数据时,那么你可以使用 global.provide
选项。
¥When your Component uses inject
and you need to pass data with provide
, then you can use the global.provide
option.
vue
<template>
<div>
{{ value }}
</div>
</template>
<script setup>
const value = inject('my-key')
</script>
单元测试可以简单地如下所示:
¥The unit test could simply look like:
typescript
test('renders correct data', () => {
const wrapper = mount(MyComponent, {
global: {
provide: {
'my-key': 'some-data'
}
}
})
expect(wrapper.text()).toBe('some-data')
})
结论
¥Conclusion
测试没有组件和
@vue/test-utils
的简单可组合项¥test simple composables without a component and
@vue/test-utils
创建一个测试辅助组件来测试更复杂的可组合项
¥create a test helper component to test more complex composables
创建一个测试辅助组件来测试你的组件是否提供了正确的数据
provide
¥create a test helper component to test your component provides the correct data with
provide
使用
global.provide
将数据传递给使用inject
的组件¥use
global.provide
to pass data to your component which usesinject