vue3 单元测试(hooks测试)
普通单元测试
function add(a: number, b: number) {return a + b;}expect(add(1, 2)).toEqual(3);
vue中的测试
vue的hook中存在vue的生命周期,所以需要hooks在vue中运行模拟整个生命周期
为hook提供组件环境
import { mount } from '@vue/test-utils';
export function mountHook(hook: () => any, provide: { [key: string]: any } = {}) {return new Promise((resolve) => {const Comp = defineComponent({name: 'TestHookDepComponent',setup: () => {resolve(hook());},template: '<span>123</span>',});const ProviderComponent = defineComponent({name: 'TestHookProvideComponent',components: { TestHookDepComponent: Comp },provide: provide,setup: () => {},template: '<TestHookDepComponent />',});const comp = mount(ProviderComponent, { props: { name: '123' } });return comp;});
}
为了方便提供和修改hook中的其他依赖所以父组件提供ref等数据,子组件依赖的hook可获取到
测试纯hooks不依赖外部
export function testHook() {const data = ref(1);const data1 = ref(data.value + 1);watch([data.value], () => {data1.value = data.value + 1;});return {updateData: (num: number) => {data.value = num;},data,data1}
}
普通hook测试
import { mountHook } from './mountHook';
import { testHook } from './testHook';
describe('testHook', () => {it('test1', async() => {const handle = testHook(testHook);expect(handle.data.value).toEqual(1);expect(handle.data1.value).toEqual(2);handle.data.value = 2;await nextTrick();expect(handle.data1.value).toEqual(3);handle.update(4);await nextTrick();expect(handle.data1.value).toEqual(5);});
});
存在其他hook的依赖
不管vue和react都是倾向于组合式hook,所以真实开发情况都会存在外部hook的依赖,单元测试的目标是只测试自己的逻辑,无条件的信赖外部依赖
- 第三方hook
export function otherHook() {const dataRef = ref(1);onMounted(() => {dataRef.value = 2;});return {dataRef,update: () => {dataRef.value = 3;}}
}
- 待测试的hooks
import { otherHook } from './otherHook';
export function myHook() {const { dataRef, update} = otherHook();const myValue = ref(1);const myData = computed(() => {return dataRef.value + myValue.value;});return {myData,update: (val: number) => {myValue.value = val;}}
}
- 测试
import { vi } from 'vitest';
import { myHook } from './myHook';
describe('test myHook', () => {it('test', async () => {// 替换otherHook,让otherHook按照自己的预想逻辑运行vi.mock('./otherHook', () => {return {otherHook: () => {const dataRef = ref(1);return {dataRef,update: () => {}}}}});const handle = testHook(myHook);await nextTrick();expect(handle.myData.value).toEqual(2);handle.update(2);await nextTrick();expect(handle.myData.value).toEqual(3);});
});