如何 Sinon 监视由 Vue 事件触发的 Vue 组件方法?



我为了描述我的问题而完成的基本设置:

使用 vue-cli2.8.2,我基于 webpack 模板 (vue init webpack vue-test-sinon-spy( 生成了一个新项目,保留了 vue-cli 的所有默认值(除了禁用 eslint 之外的无关紧要(。

在这个 vue-cli 生成的项目中所做的更改:

  1. 我在 Hello.vue 的 h2 标签上附加了一个事件:
<h2 @click="sayHello">Essential Links</h2>
  1. 我在 Hello 组件中添加了一个方法
<script>
export default {
...
methods: {
sayHello() {
console.log('hello!')
}
}
}
</script>
  1. 我在 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
  1. yarn add --dev https://github.com/vuejs/vue-test-utils(afaiu, vue-test-utils 尚未正式发布(

  2. 触发虚拟点击事件

现在,您可以添加一个新测试,该测试将按预期运行:

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 项目,也许我误解了什么。

最新更新