Vue.js单元测试 - 以异步数据

问题描述:

项目模拟服务:https://github.com/marioedgar/webpack-unit-testVue.js单元测试 - 以异步数据

我有我与VUE CLI产生Vue.js应用程序。我只是编辑的HelloWorld的成分有一些来从我的测试服务一些异步数据,你可以看到,在这里:

<template> 
 
    <h1>{{ message }}</h1> 
 
</template> 
 

 
<script> 
 
    import service from './test.service' 
 
    export default { 
 
    name: 'HelloWorld', 
 
    created() { 
 
     service.getMessage().then(message => { 
 
     this.message = message 
 
     }) 
 
    }, 
 
    data() { 
 
     return { 
 
     message: 'A' 
 
     } 
 
    } 
 
    } 
 
</script> 
 
<style scoped> 
 
</style>

测试服家住在同一目录下,是非常简单的:

class Service { 
 
    getMessage() { 
 
    return new Promise((resolve, reject) => { 
 
     console.log('hello from test service') 
 
     resolve('B') 
 
    }) 
 
    } 
 
} 
 

 
const service = new Service() 
 
export default service

所以为了给M

https://vue-loader.vuejs.org/en/workflow/testing-with-mocks.html

因此,这里是我的测试,是几乎相同的例子:

玉珠这项服务,因为官方文档在这里描述了使用的WebPack VUE装载机IM注入模拟服务

import Vue from 'vue' 
 
const HelloInjector = require('!!vue-loader?inject!../../../src/components/HelloWorld') 
 

 
const Hello = HelloInjector({ 
 
    // mock it 
 
    './test.service': { 
 
    getMessage() { 
 
     return new Promise((resolve, reject) => { 
 
     resolve('C') 
 
     }) 
 
    } 
 
    } 
 
}) 
 

 
describe('HelloWorld.vue',() => { 
 
    it('should render',() => { 
 
    const vm = new Vue({ 
 
     template: '<div><test></test></div>', 
 
     components: { 
 
     'test': Hello 
 
     } 
 
    }).$mount() 
 
    expect(vm.$el.querySelector('h1').textContent).to.equal('C') 
 
    }) 
 
})

有两个问题我面对:

  1. 测试失败,因为断言在解决模拟诺言之前正在执行。根据我的理解,这是因为当我进行断言时,vue生命周期还没有完全完成。常见的图案,以等待下一个周期将是wrapp周围跟旁边剔功能像这样我的说法:

it('should render', (done) => { 
 
    const vm = new Vue({ 
 
     template: '<div><test></test></div>', 
 
     components: { 
 
     'test': Hello 
 
     } 
 
    }).$mount() 
 
    Vue.nextTick(() => { 
 
     expect(vm.$el.querySelector('h1').textContent).to.equal('C') 
 
     done() 
 
    }) 
 
    })

然而,这并没有工作,除非我窝3个nextTicks ,这对我来说似乎非常黑客。有什么我错过了让这个工作?这个例子似乎非常简单,但我不能让这个测试通过,而不很多nextTicks的

  1. 我不断收到一个奇怪的错误,间歇性地......这样的警告显示出来的时间大概50%,在不洽所有。

[VUE警告]无法安装部件:模板或呈现功能没有被定义

再次,这仅发生有时。我可以在没有任何更改的情况下运行相同的单元测试,并且会在50%的时间内向我显示此消息。

+0

这里是链接到我的公共回购: https://github.com/marioedgar/webpack-unit-test –

我真的无法弄清楚为什么有时组件未能挂载。我甚至不确定它是否与注射器有关,但无论如何,我通过不使用它来保持测试一致;改为尝试不同的方法。

如果服务通过props注入而不是直接使用,则该组件可能更易于测试。

<template> 
    <div> 
    <h1>{{ message }}</h1> 
</div> 
</template> 

<script> 
    import service from './test.service' 

    export default { 
    name: 'HelloWorld', 
    created() { 
     this.service.getMessage().then(message => { 
     this.message = message 
     }) 
    }, 
    data() { 
     return { 
     message: 'A' 
     } 
    }, 
    props: { 
     service: { 
     default: service 
     } 
    } 
    } 
</script> 
<style scoped> 
</style> 

这使得喷射器不必要的,因为嘲笑服务可以代替传递给在构造使用propsData的组件。

import Vue from 'vue' 

import Async from '@/components/Async' 

const service = { 
    getMessage() { 
    return new Promise((resolve, reject) => { 
     resolve('C') 
    }) 
    } 
} 

describe('Async.vue',() => { 
    let vm 
    before(() => { 
    const Constructor = Vue.extend(Async) 
    vm = new Constructor({ 
     propsData: { 
     service: service 
     } 
    }).$mount() 
    }) 
    it('should render', function() { 
    // Wrapping the tick inside a promise, bypassing PhantomJS's lack of support 
    return (new Promise(resolve => Vue.nextTick(() => resolve()))).then(() => { 
     expect(vm.$el.querySelector('h1').textContent).to.equal('C') 
    }) 
    }) 
}) 
+0

我喜欢这比使用注射器,这并解决的问题之一我正面临着。不幸的是,额外的蜱是必要的。我想知道是否可以在before()中做到这一点,以避免在每个测试中的所有额外的代码。这或我可以添加一个简单的异步帮助器功能。 –

+0

你是对的。使用摩卡的'之前'测试只能进入组件,直到完全安装的组件,所以只需要一个滴答。我改变了代码来反映这一点。 –