仅当使用括号调用函数时,才能通过Vue模板中的函数调用测试 [英] Test on function call in Vue template only passes if the function is called with parentheses

查看:350
本文介绍了仅当使用括号调用函数时,才能通过Vue模板中的函数调用测试的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在将Vue v2.6与Jest(v24.9)和Vue-Test-Utils(v1.03)结合使用.

I am using Vue v2.6 with Jest (v24.9) and Vue-Test-Utils (v1.03).

为了模拟一个方法,我看到了两种不同的语法,

In order to mock a method I have seen two different syntaxes,

wrapper.vm.updateCart = jest.fn();

wrapper.setMethods({ updateCart: jest.fn() });

,但第一个未记录,而第二个已弃用(请参见

but the first is not documented, while the second is deprecated (see docs).

问题在于,使用这两种方法时,进行测试通过的唯一方法是调用带有模板内括号的方法,这很奇怪,因为我以某种方式阅读的所有文档都鼓励使用不带括号的方法在模板中.

The problem is that with both these methods, the only way to make a test pass is to call the method with the parentheses inside the template, which is weird because all the docs I've read somehow encourage to use methods without parentheses in the templates.

所以这个测试:

test('Click on .btn calls the right function', () => {
    const wrapper = shallowMount(Modal, {
        propsData: {
            validate: jest.fn(),
        },
    });
    wrapper.setMethods({ updateCart: jest.fn() });
    const $btn = wrapper.find('.btn');
    $btn.trigger('click');
    expect(wrapper.vm.updateCart).toHaveBeenCalled();
});

仅当我用括号调用该方法时才会通过:

will only pass if I call the method with parentheses:

<button class="btn" @click="updateCart()">
  {{ dictionary('remove') }}
</button>

,但否则将失败(例如,使用@click="updateCart").

but will fail otherwise (eg. using @click="updateCart").

哪种正确的语法可以测试模板中的事件正在调用函数?

Which is the right syntax to test that an event in a template is calling a function?

为什么要在文档中使用弃用警告(此处此处 )将setMethod api定义为反模式?

And why the deprecation warning in the docs (here and here) define the setMethod api as an anti-pattern?

仅测试模板中的事件是否触发函数可能是错误的,因为该行为应已由框架(Vue)保证,而我们只应专注于测试函数本身?

Maybe it is just wrong to only test that an event in a template triggers a function because this behavior should already be guaranteed by the framework (Vue) and instead we should only focus on testing the function itself?

编辑07/02/2020

我还尝试了另一种语法:

I have also tried a different syntax:

const spy = jest.spyOn(wrapper.vm, 'updateCart');
const $btn = wrapper.find('.btn');
$btn.trigger('click');
expect(spy).toHaveBeenCalled();

可以防止覆盖该方法,并替换对setMethods的调用,但是仍然只有在使用括号调用该函数时,测试才能通过.

which prevents from overwriting the method and replaces the call to setMethods, but still the test only passes when the function is called with parentheses.

推荐答案

同时支持@click="updateCart"@click="updateCart()"语法变体,这令人困惑,因为Vue DSL允许在v-on中提供表达式.前者将updateCart方法用作事件处理程序,而后者将根据组件实例评估表达式,而不仅限于方法.

Both @click="updateCart" and @click="updateCart()" syntax variations are supported, which is confusing because Vue DSL allows to provide expressions in v-on. The former uses updateCart method as event handler, while the latter evaluates the expression against component instance and isn't limited to methods.

@click="updateCart()",因为表达式通常在Vue模板中使用,并且@click="notAFunction"静默失败,而@click="notAFunction()"引发错误.这还可以通过以下方式对其进行监视:

@click="updateCart()" is preferable for consistency reasons because expressions are commonly used in Vue templates, also @click="notAFunction" silently fails while @click="notAFunction()" throws an error. This also allows to spy on it with:

jest.spyOn(wrapper.vm, 'updateCart');

否则,在组件实例化之前需要侦听该方法:

Otherwise the method needs to be spied before component instantiation:

jest.spyOn(Modal.methods, 'updateCart');
const wrapper = shallowMount(Modal);

已弃用setMethod:

没有明确的方法可以替换setMethods,因为它确实取决于 根据您以前的用法.它很容易导致依赖于 实施细节,不建议使用.

There's no clear path to replace setMethods, because it really depends on your previous usage. It easily leads to flaky tests that rely on implementation details, which is discouraged .

...

要存根复杂的方法,请从组件中提取它并进行测试 隔离.要断言某个方法已被调用,请使用测试运行程序执行以下操作: 监视它.

To stub a complex method extract it from the component and test it in isolation. To assert that a method is called, use your test runner to spy on it.

关于测试实现的关注是主观的,因为这通常不是一件坏事.提取是否实际取决于实际情况,因为一个功能需要被提取到另一个模块才能被监视.

The concerns about testing the implementation are subjective because it's often not a bad thing. It depends on the case whether the extraction is practical, because a function needs to be extracted to another module in order to be spyable.

对于updateCart,足以模拟更新carе的底层API,而不是方法本身.

As for updateCart, it may be enough to mock underlying API that updates the carе, not the method itself.

使用存根方法或至少监视真实方法来测试点击事件可能仍然有用.以这种方式测试的是模板,而不仅仅是框架的行为.没有间谍,未知是由于btn还是updateCart而导致测试失败.

It still may be useful to test click event with stubbed method, or at least spy on real method. It's the template that is tested this way, not just the behaviour of the framework. Without a spy, it's unknown whether the test fails because of btn or updateCart.

这篇关于仅当使用括号调用函数时,才能通过Vue模板中的函数调用测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆