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

查看:30
本文介绍了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?

以及为什么文档中的弃用警告(此处

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.

使用 stubbed 方法测试点击事件仍然可能有用,或者至少监视真实方法.以这种方式测试的是模板,而不仅仅是框架的行为.没有spy,不知道测试失败是因为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天全站免登陆