vue.js test-utils 为啥我的 onSubmit 函数 mock 没有被调用?

Posted

技术标签:

【中文标题】vue.js test-utils 为啥我的 onSubmit 函数 mock 没有被调用?【英文标题】:vue.js test-utils Why my onSubmit function mock is not called?vue.js test-utils 为什么我的 onSubmit 函数 mock 没有被调用? 【发布时间】:2019-03-09 14:40:33 【问题描述】:

我正在尝试使用以下规范文件测试提交表单事件:

ContactForm.spec.js

import Vue from "vue";
import Vuex from "vuex";
import  storeMock  from "./mocks.js";
import VeeValidate from "vee-validate";

import i18n from "@/locales";
import Vuetify from "vuetify";

import  mount, shallowMount  from "@vue/test-utils";
import ContactForm from "@/components/Home/ContactForm.vue";

Vue.use(Vuex);
Vue.use(VeeValidate,  errorBagName: "errors" );
Vue.use(Vuetify);

describe("ContactForm.vue", () => 
  let wrapper;
  let store = new Vuex.Store(storeMock);

  const v = new VeeValidate.Validator();

  beforeEach(() => 
    const el = document.createElement("div");
    el.setAttribute("data-app", true);
    document.body.appendChild(el);
  );

  it("submit valid form when click submit", async () => 
    // given
    const getters = 
        language: () => 
          return "fr";
        ,
        "authentication/loading": () => 
          return false;
        
      ,
    store = new Vuex.Store( getters );

    // const sendMessageMock = jest.fn( () => Promise.resolve() );
    const sendMessageMock = jest.fn();
    const options = 
      sync: false,
      store,
      provide: () => (
        $validator: v
      ),
      i18n,
      mocks : 
        sendMessage: sendMessageMock
      
    ;
    // when
    wrapper = shallowMount(ContactForm, options);
    const contactForm = wrapper.find('#contactForm');
    const submitBtn= wrapper.find('#btnSend');
    // console.log(contactForm.html());
    // when
    contactForm.trigger('submit.prevent');
    // then
    expect(sendMessageMock.called).toBe(true);
  );
);

但是这个测试没有通过……

console.log

✕ submit valid form when click submit (157ms)

● ContactForm.vue › 点击提交时提交有效表单

expect(received).toBe(expected) // Object.is equality

Expected: true
Received: undefined

Difference:

  Comparing two different types of values. Expected boolean but received undefined.

  77 |     contactForm.trigger('submit.prevent');
  78 |     // then
> 79 |     expect(sendMessageMock.called).toBe(true);
     |                                    ^
  80 |   );
  81 | );
  82 |

  at Object.toBe (tests/unit/ContactForm.spec.js:79:36)
  at tryCatch (node_modules/regenerator-runtime/runtime.js:62:40)
  at Generator.invoke [as _invoke] (node_modules/regenerator-runtime/runtime.js:296:22)
  at Generator.prototype.(anonymous function) [as next] (node_modules/regenerator-runtime/runtime.js:114:21)
  at step (node_modules/@babel/runtime/helpers/builtin/asyncToGenerator.js:10:30)
  at _next (node_modules/@babel/runtime/helpers/builtin/asyncToGenerator.js:25:9)
  at node_modules/@babel/runtime/helpers/builtin/asyncToGenerator.js:32:7

这里是要测试的组件vue

ContactForm.vue

<template>
  <form id="contactForm" onSubmit="sendMessage">
    <input v-model="language" type='hidden' name='locale'>
    <v-layout row wrap align-center>
        .../...
    </v-layout>
    <v-text-field
        .../...
    </v-text-field>
    <v-textarea .../... ></v-textarea>
    <v-btn round @click="clear">.../...</v-btn>
    <v-btn id="btnSend" round large color="primary" type="submit">Submit</v-btn>
  </form>
</template>

<script>
import  mapGetters  from "vuex";
.../...
import router from "@/router";

export default 
  name: "contactForm",
  data() 
    return 
         .../...
    ;
  ,
  computed: 
    ...mapGetters(["language"]),
    ...mapGetters("authentication", ["loading"]),
    honorificPrefix: function() 
        .../...
    
  ,
  watch: 
    language(newLanguage) 
          .../...
    
  ,
  methods: 
    setPrefix: function(value) 
          .../...
    ,
    sendMessage: function() 
        .../...
    ,
    clear: function() 
        .../...
    
  ,
  mounted() 
      .../...
  
;
</script>

欢迎反馈...

【问题讨论】:

【参考方案1】:

已解决...

    更改表单标签

    删除 mocks:在 shallowMount() 中阻塞并使用 setMethods() 将 sendMessage() 替换为 sendMessageMock()

           it("submit valid form when click submit", async () => 
        // given
        const getters = 
            language: () => 
              return "fr";
            ,
            "authentication/loading": () => 
              return false;
            
          ,
        store = new Vuex.Store( getters );
    
        const sendMessageMock = jest.fn();
        const options = 
          sync: false,
          store,
          provide: () => (
            $validator: v
          ),
          i18n
        ;
        // when
        wrapper = shallowMount(ContactForm, options);
        wrapper.setMethods( sendMessage: sendMessageMock );
        const contactForm = wrapper.find('#contactForm');
        // when
        contactForm.trigger('submit.prevent');
        // then
        expect(sendMessageMock).toBeCalled();
      );
    

【讨论】:

以上是关于vue.js test-utils 为啥我的 onSubmit 函数 mock 没有被调用?的主要内容,如果未能解决你的问题,请参考以下文章

带有 vue-test-utils 和 Jest 的 Vue.js 单元测试用例失败

为啥我的 Vue.js 项目没有显示我的网站图标?

Vue.js:为啥我的单文件组件没有在我的模板中呈现/显示

django & Vue.js:为啥我的 VueJs 组件没有显示在前端?

Vue.js 父子组件,为啥我的 prop 在子组件中还没有?

为啥我的页面可以获取 Vue.js 2 数据属性但它不是响应式的?