【问题标题】:Correctly testing an event handler in Vue component正确测试 Vue 组件中的事件处理程序
【发布时间】:2019-11-22 11:39:32
【问题描述】:

我有一个带有锚标记的组件,该组件带有关联的处理程序 onSelectLink()。

<a
  :href="$t('footer.termsUrl')"
  target="_blank"
  name="termsAndConditions"
  @click="onSelectLink($event.target.name)">{{ $t('terms') }}</a>

onSelectLink() 函数...

onSelectLink (buttonName) {
      buttonName === 'termsAndConditions'
        ? this.logButtonClick(ANALYTICS.TERMS_AND_CONDITIONS)
        : this.logButtonClick(ANALYTICS.PRIVACY_POLICY)
    }

我的单元测试

describe('onSelectLink()', () => {
    it('[positive] should track analytics when user selects `Terms and Conditions` link', () => {
      const buttonName = 'termsAndConditions'
      jest.spyOn(wrapper.vm, 'onSelectLink')

      wrapper.find('a').trigger('click')
      wrapper.vm.onSelectLink(buttonName)

      expect(wrapper.vm.logButtonClick).toHaveBeenCalledWith(ANALYTICS.TERMS_AND_CONDITIONS)
    })

    it('[positive] should track analytics when user selects `Privacy Policy` link', () => {
      const buttonName = 'privacyPolicy'
      jest.spyOn(wrapper.vm, 'onSelectLink')

      wrapper.find('a').trigger('click')
      wrapper.vm.onSelectLink(buttonName)

      expect(wrapper.vm.logButtonClick).toHaveBeenCalledWith(ANALYTICS.PRIVACY_POLICY)
    })

我的问题是:

  1. 这些测试是否每个都调用 onSelectLink() 两次?

  2. 我真的需要使用“wrapper.find('a').trigger('click')”

  3. 这是确保 onSelectLink() 使用正确的参数调用的好/稳健的测试吗?

当我注释掉“wrapper.find('a').trigger('click')”时,测试似乎仍然通过了。我以为我必须触发 DOM 事件,然后调用处理程序。

【问题讨论】:

    标签: javascript vue.js jestjs vue-test-utils


    【解决方案1】:

    您当前在每个测试中触发了两次onSelectLink

    曾经

    wrapper.find('a').trigger('click') // normal flow
    

    还有一次

    wrapper.vm.onSelectLink(buttonName) // you run `onSelectionLink` directly on vm
    

    原则上,第二个是错误的。您不想通过直接在 vm 上调用该方法来触发该方法,因为您的用户不能这样做。
    他们可以做到这一点的唯一方法是点击链接,这就是你应该测试的。

    const logger = jest.spyOn(wrapper.vm, 'logButtonClick')
    expect(logger).not.toHaveBeenCalled();
    wrapper.find('a[name="termsAndConditions"]').trigger('click')
    expect(logger).toHaveBeenCalledWith(ANALYTICS.TERMS_AND_CONDITIONS);
    

    请记住,您始终可以在测试中使用 console.log(),您将在 CLI 中看到记录的值并了解发生了什么。

    【讨论】:

    • 一件事,在另一个组件中,我有一个带有 4 个不同案例的开关/案例。每个案例都类似于“termsAndConditions”和“privacyPolicy”等。您建议的更准确的测试非常适用于我上面的 onSelect() 函数。但是,使用 switch/case 时,语句 expect(logger).not.toHaveBeenCalled() 无法通过下一次测试。例如,测试一个,“termsAndConditions”通过,然后下一个,“privacyPolicy”失败,依此类推。可以做些什么来清除以前的呼叫。另外,发生这种情况是因为测试套件正在读取一堆函数调用吗?
    • 我相信调用者的结果实际上是一个数组,但是对于它只被调用一次的情况expect(caller) 自动返回它唯一的调用 ([0]) - 因为这是最常见的情况。我可能是错的,我现在没有办法测试。但我愿意expect(caller[0]).toEqual(yourFirstCall) &amp;&amp; expect(caller[1]).toEqual(yourSecondCall)
    • @KevinT,但是,您不必在同一个测试中测试它们。您可以在单独的测试中对它们进行测试,它们将是很好的测试(例如,如果其中一个有任何问题,则该特定测试将失败)。但我明白你希望在同一个测试中测试它们。看起来更优雅。
    • 是的,我有一个测试套件和 4 个“it”块。我的代码审查员会抱怨拆散他们!
    • test 我的意思是it 块的意思。而且,事实上,它们是同义词。 it(description, handler)test(description, handler) 的别名。
    猜你喜欢
    • 2017-07-09
    • 1970-01-01
    • 1970-01-01
    • 2020-09-18
    • 2019-08-11
    • 1970-01-01
    • 2022-01-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多