繁体   English   中英

为什么 jest.spyOn() 有时不适用于 Vue 组件的方法?

[英]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()的初始断言与这里的第一个测试一样有效。

logOutshowLogOutModal方法之间的区别在于它们的使用方式。

logOut被称为常规方法:

this.logOut();

并且showLogOutModal作为回调传递:

  <v-btn
    v-if="isLoggedIn"
    class="button-log-out"
    text
    @click="showLogOutModal"

this.showLogOutModalthis.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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM