单元测试一个打字稿vue组件

Posted

技术标签:

【中文标题】单元测试一个打字稿vue组件【英文标题】:Unit test a typescript vue component 【发布时间】:2017-10-26 08:38:27 【问题描述】:

我需要能够测试我的组件(方法、计算属性、数据……)。但是,当我在单元测试中导入我的 vue 组件时:

import Pagination from 'src/components/shared/pagination.vue'
import  newComponent  from '../component-factory'

describe('pagination.vue', () => 
    const propsData = 
        metadata: 
            page: 2,
            records: 155,
            total: 11,
        ,
        perPage: 15,
    

    it('should have correct number of records', () => 
        const ctor = Vue.extend(Pagination)
        const vm = new ctor(propsData).$mount()
        expect(vm.firstRecord).toBe(16)
        expect(vm.lastRecord).toBe(30)
    )
...

vm 的类型为 Vue,因此没有 firstRecord/lastRecord 属性。使用 karma 运行测试显示成功,但 typescript 编译器吐出错误:

ERROR in ./tests/shared/pagination.spec.ts
(16,19): error TS2339: Property 'firstRecord' does not exist on type 'Vue'.

ERROR in ./tests/shared/pagination.spec.ts
(17,19): error TS2339: Property 'lastRecord' does not exist on type 'Vue'.

我尝试过投射:

...
        const vm = new ctor(propsData).$mount() as Pagination
...

但这会导致 VSCode 中出现警告:

[ts] Cannot find name 'Pagination'.

并且具有将vm 视为any 类型的效果,这完全适得其反。

我认为这一切都源于使用.vue文件时必须添加声明:

declare module '*.vue' 
    import Vue from 'vue'
    export default typeof Vue

这清楚地将所有.vue 文件的类型设置为Vue,这不是完全 谎言,但也没有帮助......有什么建议吗?我做错了什么?

为了将来参考,我尝试使用 vuetype 为每个.vue 文件生成.d.ts 文件,但遇到了this issue。此外,there is a request 使 .vue 成为打字稿生态系统中的一等公民,这将消除这个问题。而且,我刚刚添加了一个vue language service extension的请求

【问题讨论】:

【参考方案1】:

在 Vue 2.5 之前,如果您不打算使用 vue-class-component,他们的 TypeScript 文档页面建议导出扩展 Vue 的接口。您可以导出此接口以在您的测试中使用,以转换您的组件实例。该建议已从文档中删除,但我无法弄清楚如何将我的测试更改为不需要接口。

看起来 vuetype 可以为你生成这些接口,但我只是手动创建它们。

这是一个大大简化的示例,但您可以在界面中定义任何您将在 vm 上引用的内容,即数据、道具、方法:

// NOTE: Make sure your interface extends `Vue`!
export interface PaginationComponent extends Vue 
  firstRecord: number,
  lastRecord: number


export default 
  name: 'Pagination',
  data: function() 
    return 
      firstRecord: 16,
      lastRecord: 30,
    
  

对于您的测试,您可以将组件实例转换为导出接口的类型:

import Pagination, PaginationComponent from 'src/components/shared/pagination.vue'

describe('pagination', () => 
  it('should know about component data fields', () => 
    const ctor = Vue.extend(Pagination)
    const vm : PaginationComponent = new ctor().$mount()
    expect(vm.firstRecord).toBe(16)
    expect(vm.lastRecord).toBe(30)
  )
)

【讨论】:

以上是关于单元测试一个打字稿vue组件的主要内容,如果未能解决你的问题,请参考以下文章

如何对这个从管道可观察到的错误捕获的 Angular 打字稿 Http 错误拦截器进行单元测试?

如何在 AngularJS2“final”中对组件进行单元测试?

从 CLI 生成的新 vue 3 项目的单元测试中出错

如何对第一个Vue.js组件进行单元测试 (上)

第1664期Vue组件库工程探索与实践之单元测试

使用 Jest 在 Vue 中为组件中的方法编写单元测试