【问题标题】:How can I spy on a function from setup in vuejs3?如何从 vuejs3 中的 setup 中监视函数?
【发布时间】:2022-02-13 03:25:31
【问题描述】:

我在setup() 内部的组件中有一个函数:

export default defineComponent({
  setup() {
    const handleResume = async () => {
      msg.value = {}
      try {
      } catch (err) {
      }
    }
    return { handleResume }
  }
})

现在在我的测试中,我想创建一个像这样的间谍函数:

import App from '@/views/Frame'
jest.spyOn(App, 'handleResume')

但我收到此错误:

Cannot spy the handleResume property because it is not a function; undefined given instead

【问题讨论】:

    标签: vue.js jestjs vuejs3 vue-composition-api


    【解决方案1】:

    这需要 Vue 3.2.31(昨天发布),它添加了 support for mocking Proxy methods,启用了对 wrapper.vm from @vue/test-utils 的间谍。

    您可以使用expose property from the context argument 公开来自setup() 的方法(或其他数据)。例如,此组件仅在测试中公开handleResume

    <!-- MyComponent.vue -->
    <script>
    import { defineComponent } from 'vue'
    
    export default defineComponent({
                       ?
      setup(props, { expose }) {
        const handleResume = async () => true
    
        if (process.env.NODE_ENV === 'test') {
            ?
          expose({ handleResume })
        }
    
        return { handleResume }
      }
    })
    </script>
    
    <template>
      <button @click="handleResume">Click</button>
    </template>
    

    如果您有&lt;script setup&gt;,请使用defineExpose() macro

    <!-- MyComponent.vue -->
    <script setup>
    const handleResume = async () => true
    
    if (process.env.NODE_ENV === 'test') {
           ?
      defineExpose({ handleResume })
    }
    </script>
    

    然后从wrapper.vm窥探暴露的handleResume

    // MyComponent.spec.js
    import { shallowMount } from '@vue/test-utils'
    import MyComponent from '@/components/MyComponent.vue'
    
    describe('MyComponent', () => {
      it('handles resume', async () => {
        const wrapper = shallowMount(MyComponent)
                                             ?
        const handleResume = jest.spyOn(wrapper.vm, 'handleResume')
    
        await wrapper.find('button').trigger('click')
        expect(handleResume).toHaveBeenCalled()
      })
    })
    

    demo

    【讨论】:

    • 这似乎只有在模板中使用该函数时才有效。如果模板中没有使用函数怎么办?这是您使用此示例更新的演示,它没有通过。 Demo
    • 我认为问题在于handleResume2 已经在内部handleResume 周围有一个闭包,测试无法访问该闭包。
    • 感谢您的回复。我想我不是 100% 确定你的意思。我们不应该能够监视handleResume,即使它在handleResume2 中被调用?如果在这种情况下调用handleResume,您将如何测试?如果你愿意的话,也许你可以用这个场景更新那个演示;我不确定如何自己完成这项工作,而且我已经做了一段时间了。谢谢!
    • @CalebWaldner 有人发布了与您类似的问题。见answer
    【解决方案2】:

    您必须将设置从对象切换到返回对象的函数。所以你的设置应该是这样的:

    setup() {
      const handleResume = async () => {
            msg.value = {}
            try {
              
            } catch (err) {
             
            }
          }
          
      return { handleResume }
    }
         

    在这之后你有两个选择,你可以使用@vue/test-utils,将组件作为包装器挂载到测试文件中,你应该可以通过 wrapper.vm.handleResume 访问你的函数。其他解决方案,您可以将设置导出为可组合并将可组合导入测试而不是安装组件。

    【讨论】:

    • 我想模拟这个handleResume
    猜你喜欢
    • 2021-02-09
    • 2023-03-23
    • 2017-06-15
    • 2017-10-20
    • 2018-08-28
    • 2020-11-21
    • 1970-01-01
    • 1970-01-01
    • 2019-01-12
    相关资源
    最近更新 更多