最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Test on function call in Vue template only passes if the function is called with parentheses - Stack Overflow

programmeradmin3浏览0评论

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();

and

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.

So this test:

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>

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?

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?

EDIT 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();

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.

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();

and

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.

So this test:

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>

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?

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?

EDIT 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();

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.

Share edited Jul 2, 2020 at 17:20 Giorgio Tempesta asked Jul 2, 2020 at 12:58 Giorgio TempestaGiorgio Tempesta 2,0591 gold badge26 silver badges38 bronze badges 1
  • 1 Even today with Vitest + Vue 3 (position API) + Vue Testing Library, if you don't put parenthesis on the events on child ponents the spy won't register the call. I found out what I needed to do thanks to this post :) – zenw0lf Commented Sep 13, 2022 at 16:03
Add a ment  | 

1 Answer 1

Reset to default 6

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 ponent instance and isn't limited to methods.

@click="updateCart()" is preferable for consistency reasons because expressions are monly 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 ponent instantiation:

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

The deprecation of setMethod has been explained:

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 plex method extract it from the ponent 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.

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

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.

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论