Vue 使用 Jest 开发单元测试

单元测试的作用毋庸置疑能带来很多好处,但是如何去写好单元测试,个人认为是很困难的,现在依然感觉写的很差,仅仅只是能把单元测试写出来。本篇文章主要记录一下一些踩过坑的场景,并不能指导写的更好。

注意:对于基础导入组件的方法不在这里做展开且大部分方法都做了简化方便理解

对于生命周期中的函数如何写测试方法

假设代码如下,mounted 有一个 init 方法

/** --- LoginForm --- **/
mounted() {
    this.init();
}
复制代码

对于生命周期函数,目前没有找到更合适的写法,只有 mount 的时候初始化, 例子只是简单判断一下 init 是否被调用了,实际运用的时候可以结合 init 里的方法去断言其他更加具有代表性的结果

it('LoginForm 初始化时,init 是否被调用', () => {
    const init = jest.fn();
    const options = {
        methods: { init }
    };
    shallowMount(LoginForm, options);
    expect(init).toBeCalled();
})
复制代码

注意: 写单元测试的时候能用 shallowMount 的时候就不要用 mount

注意:此种方法 jest 其实并不建议,会有警告,但是当前没有找到更好的写法,如有大佬能提供,欢迎评论区留言

对于嵌套了 try catch 的方法如何写测试方法

假设有一个请求在 finally 中需要将 loading 置为 false,如下

/** --- LoginForm --- **/
methods: {
    async getInfo() {
        this.loading = true;
        try {
           await $getInfo();
        } catch (error) {
            throw new Error(error);
        } finally {
            this.loading = false;
        }
    }
}
复制代码

这种其实只要在对应的 try catch 中写断言就行,如下

it('获取信息失败成功与否,loading 都会消失', async () => {
    const wrapper = shallowMount(LoginForm);
    try {
        await wrapper.vm.getInfo();
    } finally {
        expect(wrapper.vm.loading).toBeFalsy();
    }
})
复制代码

对于 vue 中的路由变化如何写测试方法

假设一个方法就是跳转到 dashboard 页面,如下

/** --- LoginForm path: '/login' **/
methods: {
    goDashboard() {
        this.$router.push({
            name: 'dashboard'
        })
    }
}
复制代码

这种一般就需要使用 localVue 实例化路由,然后去模拟跳转了,具体如下

import VueRouter from 'vue-router';
import routes from '@/router/login';
import { shallowMount, createLocalVue } from '@vue/test-utils';

const router = new VueRouter({ routes });
const localVue = createLocalVue();
localVue.use(VueRouter);

it('跳转到 dashboard 页面', () => {
    const options = {
      localVue,
      router
    };
    const wrapper = shallowMount(LoginForm, options);
    router.push({
      name: 'login'
    });
    wrapper.vm.goDashboard();

    expect(router.currentRoute.path).toMatch('/dashboard');
})
复制代码

构造异步请求返回值 --- 单次 mock,不变更

业务中如果导入了 api 方法,如下

扫描二维码关注公众号,回复: 13620492 查看本文章
import { $login } from '@/apis/login';
复制代码

这边对其结果做单次 mock,无法变更,如下

jest.mock('@/apis/login', () => ({
    $login: () => 
        Promise.resolve({
            code: 200,
            message: 'success'
        })
})
复制代码

注意: 不能将 mock 方法写在任意的 it 下,以及 beforeAll 这种钩子函数里,需要写在最外层作用域下

构造异步请求返回值 --- 多次 mock,可变更

这种就可以任意来构造返回值来对其做不同场景的断言,如下

import * as loginApi from '@/apis/login';
it('mock 接口返回值', async () => {
    loginApi.$login = jest.fn(() =>
      Promise.resolve({
            code: 200,
            message: 'success'
        })
    );
    ...
})
复制代码

这样就可以任意去构造你的返回包括 reject 错误场景的构造断言

未完待续...

对于计时器如何写测试方法

对于组件销毁场景如何写测试方法

对于表单验证如何写测试方法

对于弹窗、messageBox 这些场景如何去写测试方法

子组件如何 mock

猜你喜欢

转载自juejin.im/post/7042973138463752199