![](/img/trans.png)
[英]Using Jest, how do I spyon an extended component's method when unit testing a single file component in vue.js
[英]Why doesn't jest.spyOn() sometimes work on a Vue component's method?
我看到该方法作为事件处理程序所做的更改,但jest.spyOn(wrapper.vm, 'methodName')
在主要情况下没有捕捉到调用,但在某些测试中它以某种方式起作用。 我怀疑可能会重新渲染(可能是由于mount()
调用中的options
参数),它用jest.spyOn()
替换了原始方法,因为如果我连续两次触发事件, toHaveBeenCalled()
满足并且跟踪呼叫。
组件:
<template>
<v-app-bar
app
color="primary"
dark
class="header"
>
<router-link
:to="{name: 'User'}"
class="up-and-down-link"
>
<v-toolbar-title>Тестовое задание</v-toolbar-title>
</router-link>
<v-spacer />
<v-toolbar-items>
<v-btn
v-if="isLoggedIn"
class="button-log-out"
text
@click="showLogOutModal"
>
Выйти из профиля
</v-btn>
</v-toolbar-items>
<Modal
v-bind="modal"
@close="onModalClose"
@click:outside="onModalClose(false)"
>
Вы уверены, что хотите выйти из профиля?
</Modal>
</v-app-bar>
</template>
<script>
import { LOG_OUT } from '@/store/auth/action-types';
import { IS_LOGGED_IN } from '@/store/auth/getter-types';
import Modal from '@/components/Modal.vue';
export default {
name: 'Header',
components: { Modal },
data() {
return {
modal: {
show: false,
withConfirmation: true,
},
};
},
computed: {
isLoggedIn() {
return this.$store.getters[`auth/${IS_LOGGED_IN}`];
},
},
methods: {
showLogOutModal() {
this.modal.show = true;
},
onModalClose(confirmation = false) {
this.modal.show = false;
if (confirmation === false) return;
this.logOut();
},
logOut() {
this.$store.dispatch(`auth/${LOG_OUT}`);
this.$router.push({ name: 'Login' });
},
},
};
</script>
该测试按预期工作:
it('After confirmation of the action user is logged out and redirected to login page', async () => {
const actions = {
[LOG_OUT]: jest.fn(),
};
await store.hotUpdate({ modules: { auth: { ...auth, actions } } });
const mockedRouter = {
push: jest.fn(),
};
const wrapper = createWrapper(Header, {
data: () => ({ modal: { show: true } }),
mocks: {
$route: {},
$router: mockedRouter,
},
});
const mockedLogOutMethod = jest.spyOn(wrapper.vm, 'logOut');
await wrapper.find('.button-yes').trigger('click');
// the method's called
expect(mockedLogOutMethod).toHaveBeenCalled();
// the method performs log out and redirect
expect(actions[LOG_OUT]).toHaveBeenCalled();
expect(mockedRouter.push).toHaveBeenCalledWith({ name: 'Login' });
});
但是这个没有,尽管在此期间组件的data
发生了变化,并且我们在组件的子道具上看到了它( 'show'
变成了true
),因此确实调用了该方法,但是toHaveBeenCalled()
不能检测事实:
it("Show modal with confirmation when 'log out' button was clicked", async () => {
const wrapper = createWrapper(Header);
const mockedShowModalMethod = jest.spyOn(wrapper .vm, 'showLogOutModal');
const modal = wrapper.findComponent(Modal);
// the modal is hidden initially
expect(modal.props('show')).toBe(false);
await wrapper.find('.button-log-out').trigger('click');
// after 'log out' button is clicked the modal appears
expect(modal.props('show')).toBe(true);
expect(mockedShowModalMethod).toHaveBeenCalled();
expect(wrapper.find('.modal-confirmation').exists()).toBe(true);
});
我找到了一个解决方法:
...
const mockedShowModalMethod = jest.spyOn(Header.methods, 'showLogOutModal');
const wrapper = createWrapper(Header);
....
但是,我想找出这种行为的原因,我在这里想念什么? 我有另一个测试套件,我对jest.spyOn()
的初始断言与这里的第一个测试一样有效。
logOut
和showLogOutModal
方法之间的区别在于它们的使用方式。
logOut
被称为常规方法:
this.logOut();
并且showLogOutModal
作为回调传递:
<v-btn
v-if="isLoggedIn"
class="button-log-out"
text
@click="showLogOutModal"
this.showLogOutModal
在this.showLogOutModal
被读取以用作事件处理程序之后被jest.spyOn
模拟,因此间谍不会影响任何事情。
这可能会通过在用间谍替换wrapper.vm.showLogOutModal
后强制重新渲染来解决:
const mockedShowModalMethod = jest.spyOn(wrapper.vm, 'showLogOutModal');
await wrapper.vm.$forceUpdate();
但是问题中列出的解决方法是推荐的方法:
const mockedShowModalMethod = jest.spyOn(Header.methods, 'showLogOutModal');
const wrapper = createWrapper(Header);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.