我为了描述我的问题而完成的基本设置:
使用 vue-cli2.8.2,我基于 webpack 模板 (vue init webpack vue-test-sinon-spy
( 生成了一个新项目,保留了 vue-cli 的所有默认值(除了禁用 eslint 之外的无关紧要(。
在这个 vue-cli 生成的项目中所做的更改:
- 我在 Hello.vue 的 h2 标签上附加了一个事件:
<h2 @click="sayHello">Essential Links</h2>
- 我在 Hello 组件中添加了一个方法
<script>
export default {
...
methods: {
sayHello() {
console.log('hello!')
}
}
}
</script>
- 我在 Hello.spec 中添加了一个新测试.js
describe('Hello.vue', () => {
// ...
it('should handle click on h2 tag', () => {
const Constructor = Vue.extend(Hello)
const vm = new Constructor().$mount()
sinon.spy(vm, 'sayHello')
// [A] if I run the line below, vm.sayHello.callCount will be 0 - not as expected
vm.$el.querySelector('h2').click()
// [B] if I run the line below, vm.sayHello.callCount will be 1 - as expected
// vm.sayHello()
// vm.sayHello.callCount will be 0 or 1, depending on
// what line I execute ([A] or [B]),
// even if in both cases sayHello method is really executed
console.log('###', vm.sayHello.callCount)
})
})
当我以编程方式单击 html 标签(使用vm.$el.querySelector('h2').click()
(时,间谍不会捕获方法sayHello
的执行,因此vm.sayHello.callCount
将为 0。不是我喜欢的。
但是,如果我直接调用sayHello
(使用vm.sayHello()
(,vm.sayHello.callCount
将是 1。正如我所料。
如果我想模拟点击 html 标签 (vm.$el.querySelector('h2').click()
(,而不是直接调用sayHello
(没有vm.sayHello()
(,我如何让间谍捕获sayHello
的调用(这样vm.sayHello.callCount
将是 1(?
谢谢
这里的问题是在挂载组件时回调被绑定到事件。我不确定它在后台是如何工作的,但它就像它是点击事件范围内sayHello
方法的副本。绑定后无法对其进行修改。
之后,您将在组件方法上创建间谍。他们的行为相同,但事实并非如此。一个是间谍,一个不是。
wrapper.vm.sayHello()
执行方法(监视(wrapper.find('h2').trigger('click')
执行回调(不监视(
在挂载之前而不是之后在实例上创建组件类的间谍,它应该按预期工作。
it('should handle click on h2 tag - vue-test-utils + dummy click version', () => {
const clickSpy = sinon.spy(Hello.methods, 'sayHello')
const wrapper = mount(Hello)
...
})
(注意 Phil 对此的评论不是单元测试的有效使用。
我发现的解决方法是这样的:
安装 vue-test-utils:
yarn add --dev https://github.com/vuejs/vue-test-utils
(afaiu, vue-test-utils 尚未正式发布(触发虚拟点击事件
现在,您可以添加一个新测试,该测试将按预期运行:
describe('Hello.vue', () => {
// ...
it('should handle click on h2 tag - vue-test-utils + dummy click version', () => {
const wrapper = mount(Hello)
sinon.spy(wrapper.vm, 'sayHello')
// trigger a dummy click event
wrapper.find('h1').trigger('click')
// [A] if I run the line below, vm.sayHello.callCount will be 1 - as expected
wrapper.find('h2').trigger('click')
// [B] if I run the line below, vm.sayHello.callCount will be 1 - as expected
// wrapper.vm.sayHello()
// vm.sayHello.callCount will be 1 in both [A] and [B] cases
console.log('#####', wrapper.vm.sayHello.callCount)
})
})
这种行为太奇怪了,使 Vue 看起来更像是一个宠物项目,而不是一个 2.x.x 项目,也许我误解了什么。