【问题标题】:How to Sinon spy a Vue component method triggered by a Vue event?Sinon如何窥探Vue事件触发的Vue组件方法?
【发布时间】:2017-08-20 23:08:39
【问题描述】:

我为描述我的问题所做的基本设置:

使用 vue-cli 2.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())时,spy 不会捕获方法 sayHello 的执行,因此 vm.sayHello.callCount 将为 0。不是我喜欢的。

但是,如果我直接调用sayHello(使用vm.sayHello()),vm.sayHello.callCount 将是 1。正如我所料。

如果我想模拟对 html 标签 (vm.$el.querySelector('h2').click()) 的点击,而不是直接调用 sayHello (没有vm.sayHello())?

谢谢

【问题讨论】:

  • 这不是更好的 e2e 测试吗?我不认为单元测试应该关注 UI 交互

标签: vuejs2 sinon


【解决方案1】:

这里的问题是当组件被挂载时回调被绑定到事件。我不确定它在后台是如何工作的,但它就像点击事件范围内的sayHello 方法的副本。绑定后无法修改。

您在 components 方法之后创建了间谍。他们的行为相同,但事实并非如此。一个是间谍,一个不是。

wrapper.vm.sayHello() 执行方法(窥探) wrapper.find('h2').trigger('click') 执行回调(未监视)

在挂载之前在组件类上创建 spy,而不是在之后创建实例,它应该可以按预期工作。

it('should handle click on h2 tag - vue-test-utils + dummy click version', () =>     {
    const clickSpy = sinon.spy(Hello.methods, 'sayHello')
    const wrapper = mount(Hello)
    ...
})

【讨论】:

  • 我们也可以对数据变量做同样的事情吗?类似于: sinon.spy(Hello.data, 'datavariable') ?
  • 没有。间谍仅用于监视函数或对象方法。 abdulapopoola.com/2016/04/11/…
【解决方案2】:

(请注意Phil's comment,这不是对单元测试的有效使用。)

我发现的解决方法是这样的:

  1. 安装vue-test-utils:yarn add --dev https://github.com/vuejs/vue-test-utils(afaiu,vue-test-utils 是not officially released 尚未)

  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 项目,这可能是我误解了什么。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-10-16
    • 2017-03-29
    • 1970-01-01
    • 2015-11-18
    • 2018-10-26
    • 2021-01-20
    • 2017-08-08
    相关资源
    最近更新 更多