[单元测试]vue2.x迁移vue3.x

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

vue已经从对应的vue2.x迁移为vue3.x,可以参考官方迁移文档

遇到的其它问题记录一下方便以后迁移遇到问题时查找

环境

"@vue/cli-service": "~5.0.8",
"@vue/vue3-jest": "^27.0.0-alpha.3",
"jest": "^27.5.1",
"ts-jest": "^27.1.5",

迁移问题

vue文件中使用了全局注册组件

三方组件不是在vue文件中注册的是全局注册的所以mount该vue组件文件的时候提示无法识别三方组件

那么三方组件如何注册使用过在选项中直接添加components选项与shallow平级无效

然后找到以下注册全局组件的方式

let wrapper = mount(NoFound, {
    shallow: true,//渲染子组件但是子组件内部就不会继续渲染了哪怕设置了
    global: {//组件在全局注册时测试时的添加方法
        components: globalComponents,
        stubs:{},
        // renderStubDefaultSlot
    }
});

渲染slot

在测试的vue组件文件中存在的三方组件中存在slot默认是不渲染的如果我们希望所有的slot都被渲染出来需要以下设置

import { config } from '@vue/test-utils'
config.global.renderStubDefaultSlot = true

注册全局组件与渲染slot示例

场景
vue文件

<template>
    <a-result :status="status" :title="title" :subTitle="subTitle">
        <template #extra>
            <router-link to="/index">
                <a-button type="primary">Back Home</a-button>
            </router-link>
        </template>
    </a-result>
</template>

<script lang="ts">
export default {
    name: "no-find",
    props: {
        status: {
            default: "404"
        },
        title: {
            default: "404"
        },
        subTitle: {
            default: "Sorry"
        }
    }
};
</script>

<style scoped lang="less">
</style>

测试文件

import { mount, config } from "@vue/test-utils";
import NoFound from "@/src/components/no-found.vue";
import { Result, Button } from 'ant-design-vue';

// 模拟组件
const mockComponent = {
    template: `<div><slot></slot></div>`,
};
// 全局组件列表
const globalComponents = {
    'a-button': Button,
    'a-result': Result,
    'router-link': mockComponent,
};
beforeAll(() => {
    config.global.renderStubDefaultSlot = true
})
let wrapper;
let container;
describe("NoFound component:", () => {
    beforeEach(() => {
        wrapper = mount(NoFound, {
            shallow: true,
            global: {
                components: globalComponents
            }
        });

        container = mount(NoFound, {
            global: {
                components: globalComponents
            }
        });
    })
    it("NoFound child component slot is render,contain 'Back Home'", () => {
        //wrapper不可以
        expect(container.getComponent(mockComponent).html()).toContain("Back Home");
    });

    it("container contain result component", () => {
        expect(container.findComponent(Result).exists()).toBeTruthy();
    });
    it("wrapper contain result component ", () => {
        expect(wrapper.findComponent(Result).exists()).toBeTruthy();
    });

    it("NoFound child component Result default 404 is render", () => {
        expect(container.getComponent(Result).html()).toContain("Sorry, the page you visited does not exist");
    });

    it("NoFound child component Result pass prop data to it", () => {
        const temp = mount(NoFound, {
            props: {
                status: "500",
                title: 500,
                subTitle: 'Server error'
            },
            shallow: true,
            global: {
                components: globalComponents
            }
        });
        expect(temp.getComponent(Result).html()).toContain("Server error");
    });

    afterEach(() => {
        wrapper.unmount()
        container.unmount();//销毁组件实例
    })
});
afterAll(() => {
    config.global.renderStubDefaultSlot = false
})


以上代码的测试运行

it("NoFound child component slot is render,contain 'Back Home'", () => {
    //"wrapper 不可以"
    expect(container.getComponent(mockComponent).html()).toContain("Back Home");
});

如果测试的是wrapper则提示以下内容断言错误感觉shallow: true参数阻止了内部参数的渲染<a-result-stub title="404" subtitle="Sorry, the page you visited does not exist." status="404"></a-result-stub>所以内部的slot更加无法渲染所以无法获取"Back Home"

判断组件是否存在

//正确
expect(wrapper.findComponent(NoFound).exists()).toBeTruthy()
//错误
expect(wrapper.findComponent(NoFound).exists()).toBe(true)

TypeError: window.matchMedia is not a function

这个是在使用了vue3的写法中报错了包括vue3 语法糖的写法与defineComponent的setup组合式API的写法网上有说是因为babel-jestjest,与ts-jest版本不一致导致本人更新后发现没有任何作用

在尝试过后发现是无效的无意间更改了挂载的方法

wrapper = mount(NoFound, {
    global: {
        components: globalComponents
    }
});

wrapper = shallowMount(NoFound, {
    global: {
        components: globalComponents
    }
});

我在官网看说是设置了shallow: true mount 方法与shallowMount等效的所以设置了 shallow: true的mount也不会报错TypeError: window.matchMedia is not a function。如果有报错请查看是不是存在没有设置该属性的 mount 方法

所以设置了shallow为true,所有断言渲染后属性的都不成立因为内部包括自身的组件是没有渲染的

<a-result-stub title="404" subtitle="Sorry, the page you visited does not exist." status="404"></a-result-stub>

在以后的版本之中不知是否修复但是碍于使用的是@vue/cli-service目前最高版本是5.0.8所以导致 "@vue/vue3-jest": "^27.0.0-alpha.3"只能使用该版本所以对应的jest等版本也不能升级

组件的渲染问题只能等以后可以升级或者改变脚手架后再看了

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: vue