只有在使用括号调用函数时,Vue 模板中的函数调用测试才会通过
Test on function call in Vue template only passes if the function is called with parentheses
我正在将 Vue v2.6 与 Jest (v24.9) 和 Vue-Test-Utils (v1.03) 一起使用。
为了模拟一个方法,我看到了两种不同的语法,
wrapper.vm.updateCart = jest.fn();
和
wrapper.setMethods({ updateCart: jest.fn() });
但第一个未记录,而第二个已弃用(参见 docs)。
问题是,对于这两种方法,通过测试的唯一方法是在模板中调用带有括号的方法,这很奇怪,因为我读过的所有文档都以某种方式鼓励使用方法模板中没有括号。
所以这个测试:
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();
});
只有在我用括号调用方法时才会通过:
<button class="btn" @click="updateCart()">
{{ dictionary('remove') }}
</button>
但否则会失败(例如使用 @click="updateCart"
)。
测试模板中的事件调用函数的正确语法是什么?
为什么文档中的弃用警告 (here and here) 将 setMethod
api 定义为反模式?
也许只测试模板中的事件触发函数是错误的,因为框架 (Vue) 应该已经保证了这种行为,而我们应该只专注于测试函数本身?
编辑 2020 年 7 月 2 日
我也试过不同的语法:
const spy = jest.spyOn(wrapper.vm, 'updateCart');
const $btn = wrapper.find('.btn');
$btn.trigger('click');
expect(spy).toHaveBeenCalled();
防止覆盖方法并替换对 setMethods
的调用,但仍然只有在使用括号调用函数时测试才会通过。
同时支持 @click="updateCart"
和 @click="updateCart()"
语法变体,这令人困惑,因为 Vue DSL 允许在 v-on
中提供表达式。前者使用 updateCart
方法作为事件处理程序,而后者根据组件实例评估表达式,并且不限于方法。
出于一致性原因,@click="updateCart()"
更可取,因为 Vue 模板中通常使用表达式,而且 @click="notAFunction"
静默失败,而 @click="notAFunction()"
抛出错误。这也允许监视它:
jest.spyOn(wrapper.vm, 'updateCart');
否则需要在组件实例化之前侦测该方法:
jest.spyOn(Modal.methods, 'updateCart');
const wrapper = shallowMount(Modal);
已解释 setMethod
的弃用:
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.
对测试实施的担忧是主观的,因为它通常不是坏事。抽取是否实用要看情况,因为一个函数需要抽取到另一个模块才能被窥探。
至于 updateCart
,模拟更新护理的底层 API 可能就足够了,而不是方法本身。
用 stubbed 方法测试 click 事件可能还是有用的,或者至少监视真正的方法。以这种方式测试的是模板,而不仅仅是框架的行为。没有间谍,不知道测试失败是因为 btn
还是 updateCart
.
我正在将 Vue v2.6 与 Jest (v24.9) 和 Vue-Test-Utils (v1.03) 一起使用。
为了模拟一个方法,我看到了两种不同的语法,
wrapper.vm.updateCart = jest.fn();
和
wrapper.setMethods({ updateCart: jest.fn() });
但第一个未记录,而第二个已弃用(参见 docs)。
问题是,对于这两种方法,通过测试的唯一方法是在模板中调用带有括号的方法,这很奇怪,因为我读过的所有文档都以某种方式鼓励使用方法模板中没有括号。
所以这个测试:
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();
});
只有在我用括号调用方法时才会通过:
<button class="btn" @click="updateCart()">
{{ dictionary('remove') }}
</button>
但否则会失败(例如使用 @click="updateCart"
)。
测试模板中的事件调用函数的正确语法是什么?
为什么文档中的弃用警告 (here and here) 将 setMethod
api 定义为反模式?
也许只测试模板中的事件触发函数是错误的,因为框架 (Vue) 应该已经保证了这种行为,而我们应该只专注于测试函数本身?
编辑 2020 年 7 月 2 日
我也试过不同的语法:
const spy = jest.spyOn(wrapper.vm, 'updateCart');
const $btn = wrapper.find('.btn');
$btn.trigger('click');
expect(spy).toHaveBeenCalled();
防止覆盖方法并替换对 setMethods
的调用,但仍然只有在使用括号调用函数时测试才会通过。
同时支持 @click="updateCart"
和 @click="updateCart()"
语法变体,这令人困惑,因为 Vue DSL 允许在 v-on
中提供表达式。前者使用 updateCart
方法作为事件处理程序,而后者根据组件实例评估表达式,并且不限于方法。
@click="updateCart()"
更可取,因为 Vue 模板中通常使用表达式,而且 @click="notAFunction"
静默失败,而 @click="notAFunction()"
抛出错误。这也允许监视它:
jest.spyOn(wrapper.vm, 'updateCart');
否则需要在组件实例化之前侦测该方法:
jest.spyOn(Modal.methods, 'updateCart');
const wrapper = shallowMount(Modal);
已解释 setMethod
的弃用:
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.
对测试实施的担忧是主观的,因为它通常不是坏事。抽取是否实用要看情况,因为一个函数需要抽取到另一个模块才能被窥探。
至于 updateCart
,模拟更新护理的底层 API 可能就足够了,而不是方法本身。
用 stubbed 方法测试 click 事件可能还是有用的,或者至少监视真正的方法。以这种方式测试的是模板,而不仅仅是框架的行为。没有间谍,不知道测试失败是因为 btn
还是 updateCart
.