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

时间:2017-08-20 23:08:40

标签: vuejs2 sinon

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

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

在此vue-cli生成的项目中完成的更改:

  1. 我在Hello.vue上附加了一个关于h2标签的事件:
  2. <h2 @click="sayHello">Essential Links</h2>
    
    1. 我在Hello组件中添加了一个方法
    2. <script>
      export default {
        ...
        methods: {
          sayHello() {
            console.log('hello!')
          }
        }
      }
      </script>
      
      1. 我在Hello.spec.js
      2. 中添加了一个新测试
        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标记(sayHello)上的点击,我如何让间谍捕获vm.sayHello.callCount的调用(以便vm.$el.querySelector('h2').click()为1),以及没有直接致电sayHello(没有vm.sayHello())?

        由于

2 个答案:

答案 0 :(得分:5)

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

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

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)
    ...
})

答案 1 :(得分:0)

(注意Phil's comment这不是单位测试的有效用法。)

我找到的解决方法是:

  1. 安装vue-test-utilsyarn add --dev https://github.com/vuejs/vue-test-utils(afaiu,vue-test-utils还是not officially released

  2. 触发虚拟点击事件

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

    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项目,也许我误解了一些东西。