使用 jest 和 avoriaz 时如何测试 Vuejs 组件中的异步方法

cho*_*sia 5 unit-testing vue.js jestjs vuejs2 avoriaz

例如,我有一个如下所示的组件。

\n\n
<template>\n<div id="app">\n  <button class="my-btn" @click="increment">{{ val }}</button>\n</div>\n</template>\n\n<script>\nexport default {\n  data() {\n    return {\n      val: 1,\n    };\n  },\n  methods: {\n    increment() {\n      fetch(\'httpstat.us/200\').then((response) => {\n        this.val++;\n      }).catch((error) => {\n        console.log(error);\n      });\n    },\n  },\n}\n</script>\n
Run Code Online (Sandbox Code Playgroud)\n\n

您还可以检查这个小提琴作为简化的演示

\n\n

为了对该组件进行单元测试,我编写了这样的代码。

\n\n
// Jest used here\ntest(\'should work\', () => {\n  // wrapper was generated by using avoriaz\'s mount API\n  // `val` was 1 when mounted.\n  expect(wrapper.data().val).toBe(1);\n  // trigger click event for testing\n  wrapper.find(\'.my-btn\')[0].trigger(\'click\');\n  // `val` should be 2 when the button clicked.\n  // But how can I force jest to wait until `val` was set?\n  expect(wrapper.data().val).toBe(2);\n});\n
Run Code Online (Sandbox Code Playgroud)\n\n

它没有工作,因为在完成expect之前运行fetch,但我不知道如何让笑话等到承诺函数完成。
\n那么我该如何测试这个用例呢?

\n\n

更新我尝试了 nextTick 但没有运气。

\n\n
 PASS  src/Sample.spec.js\n  Sample.vue\n    \xe2\x9c\x93 should work (31ms)\n\nTest Suites: 1 passed, 1 total\nTests:       1 passed, 1 total\nSnapshots:   0 total\nTime:        1.46s\nRan all test suites.\n  console.error node_modules/vue/dist/vue.runtime.common.js:477\n    [Vue warn]: Error in nextTick: "Error: expect(received).toBe(expected)\n\n    Expected value to be (using ===):\n      2\n    Received:\n      1"\n\n  console.error node_modules/vue/dist/vue.runtime.common.js:564\n    { Error: expect(received).toBe(expected)\n\n    Expected value to be (using ===):\n      2\n    Received:\n      1\n        at /path/to/sample-project/src/Sample.spec.js:16:30\n        at Array.<anonymous> (/path/to/sample-project/node_modules/vue/dist/vue.runtime.common.js:699:14)\n        at nextTickHandler (/path/to/sample-project/node_modules/vue/dist/vue.runtime.common.js:646:16)\n        at <anonymous>\n        at process._tickCallback (internal/process/next_tick.js:188:7)\n      matcherResult: \n       { actual: 1,\n         expected: 2,\n         message: [Function],\n         name: \'toBe\',\n         pass: false } }\n
Run Code Online (Sandbox Code Playgroud)\n\n

这是完整的测试代码。

\n\n
import { mount } from \'avoriaz\';\nimport Sample from \'./Sample.vue\';\nimport Vue from \'vue\';\n\n/* eslint-disable */\n\ndescribe(\'Sample.vue\', () => {\n\n  test(\'should work\', () => {\n    const wrapper = mount(Sample);\n    // console.log(wrapper.data().val);\n    expect(wrapper.data().val).toBe(1);\n    wrapper.find(\'.my-btn\')[0].trigger(\'click\');\n    Vue.nextTick(() => {\n        // console.log(wrapper.data().val);\n        expect(wrapper.vm.val).toBe(2);\n        done();\n    })\n  });\n\n})\n
Run Code Online (Sandbox Code Playgroud)\n\n

我添加了更新2done,但仍然不起作用。这是错误消息。

\n\n
  console.error node_modules/vue/dist/vue.runtime.common.js:477\n    [Vue warn]: Error in nextTick: "Error: expect(received).toBe(expected)\n\n    Expected value to be (using ===):\n      2\n    Received:\n      1"\n\n  console.error node_modules/vue/dist/vue.runtime.common.js:564\n    { Error: expect(received).toBe(expected)\n\n    Expected value to be (using ===):\n      2\n    Received:\n      1\n        at /path/to/sample-project/src/Sample.spec.js:16:30\n        at Array.<anonymous> (/path/to/sample-project/node_modules/vue/dist/vue.runtime.common.js:699:14)\n        at nextTickHandler (/path/to/sample-project/node_modules/vue/dist/vue.runtime.common.js:646:16)\n        at <anonymous>\n        at process._tickCallback (internal/process/next_tick.js:188:7)\n      matcherResult: \n       { actual: 1,\n         expected: 2,\n         message: [Function],\n         name: \'toBe\',\n         pass: false } }\n\n FAIL  src/Sample.spec.js (7.262s)\n  \xe2\x97\x8f Sample.vue \xe2\x80\xba should work\n\n    Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.\n\n      at pTimeout (node_modules/jest-jasmine2/build/queueRunner.js:53:21)\n      at Timeout.callback [as _onTimeout] (node_modules/jsdom/lib/jsdom/browser/Window.js:523:19)\n      at ontimeout (timers.js:469:11)\n      at tryOnTimeout (timers.js:304:5)\n      at Timer.listOnTimeout (timers.js:264:5)\n\n  Sample.vue\n    \xe2\x9c\x95 should work (5032ms)\n\nTest Suites: 1 failed, 1 total\nTests:       1 failed, 1 total\nSnapshots:   0 total\nTime:        8.416s\nRan all test suites.\n
Run Code Online (Sandbox Code Playgroud)\n