在 vue-test-utils 中 mock 全局对象

馋奶兔 提交于 2020-04-28 08:20:12

<p><code>vue-test-utils</code> 提供了一种 mock 掉 <code>Vue.prototype</code> 的简单方式,不但对测试用例适用,也可以为所有测试设置默认的 mock。</p> <h2><code>mocks</code> 加载选项</h2> <p><code>mocks</code> 加载选项 是一种将任何属性附加到 <code> Vue.prototype</code> 上的方式。这通常包括:</p> <p><code>$store</code> , for Vuex</p> <p><code>$router</code>, for Vue Router</p> <p><code>$t</code> , for vue-i18n</p> <p>以及其他种种。</p> <p><code>vue-i18n </code> <strong>的例子</strong><br>我们来看一个 vue-i18n 的例子。虽然可以为每个测试用到 <code> createLocalVue </code> 并安装 <code>vue-i18n </code>,但那样可能会让事情难以处理并引入一堆样板。首先,组件 <code> &lt;Bilingual&gt; </code> 用到了 <code>vue-i18n</code>` :</p> <pre class="brush:js">&lt;template&gt; &lt;div class="hello"&gt; {{ $t("helloWorld") }} &lt;/div&gt; &lt;/template&gt;

<script> export default { name: "Bilingual" } </script>`</pre>

<p>你先在另一个文件中弄好翻译,然后通过<code> $t </code> 引用,这就是 <code> vue-i18n </code> 的工作方式。在本次测试中,虽然并不会真正关心翻译文件看起来什么样,不过还是看一看这次用到的:</p> <pre class="brush:js">export default { "en": { helloWorld: "Hello world!" }, "ja": { helloWorld: "こんにちは、世界!" } }</pre> <p>基于这个 locale,正确的翻译将被渲染出来。我们先不用 mock,尝试在测试中渲染该组件:</p> <pre class="brush:js">import { shallowMount } from "@vue/test-utils" import Bilingual from "@/components/Bilingual.vue"

describe("Bilingual", () => { it("renders successfully", () => { const wrapper = shallowMount(Bilingual) }) })</pre>

<p>通过 <code>yarn test:unit</code> 运行测试将抛出一堆错误堆栈。若仔细端详输出则会发现:</p> <p>这是因为我们并未安装<code> vue-i18n</code> ,所以全局的 <code> $t</code> 方法并不存在。我们试试 <code> mocks </code> 加载选项:</p> <pre class="brush:js">import { shallowMount } from "@vue/test-utils" import Bilingual from "@/components/Bilingual.vue"

describe("Bilingual", () => { it("renders successfully", () => { const wrapper = shallowMount(Bilingual, { mocks: { $t: (msg) => msg } }) }) })</pre>

<p>现在测试通过了!<code> mocks </code> 选项用处多多,而我觉得最最常用的正是开头提到过的那三样。</p> <p>(译注:通过这种方式就不能在单元测试中耦合与特定语言相关的内容了,因为翻译功能实际上已失效,也更无法处理可选参数等)</p> <h2>使用配置设置默认的 mocks</h2> <p>有时需要一个 mock 的默认值,这样就不用为每个测试用例都设置一遍了。可以用 <code>vue-test-utils </code> 提供的 config API 来实现。还是 <code> vue-i18n</code> 的例子:</p> <pre class="brush:js">import VueTestUtils from "@vue/test-utils"

VueTestUtils.config.mocks["mock"] = "Default Mock Value"</pre>

<p>这个示例中用到了 Jest,所以我将把默认 mock 描述在<code> jest.init.js </code>文件中 -- 该文件会在测试运行前被自动加载。同时我也会导入并应用此前用于示例的翻译对象。</p> <pre class="brush:js">//jest.init.js

import VueTestUtils from "@vue/test-utils" import translations from "./src/translations.js"

const locale = "en"

VueTestUtils.config.mocks["$t"] = (msg) => translations[locale][msg]</pre>

<p>现在尽管还是用了一个 mock 过的<code> $t</code> 函数,但会渲染一个真实的翻译了。再次运行测试,这次移除了 <code> mocks </code> 加载选项并用 <code> console.log </code>打印了 <code> wrapper.html() </code>。</p> <pre class="brush:js">describe("Bilingual", () =&gt; { it("renders successfully", () =&gt; { const wrapper = shallowMount(Bilingual)

console.log(wrapper.html())

}) })</pre>

<p>测试通过,以下结构被渲染出来:</p> <pre class="brush:js">&lt;div class="hello"&gt; Hello world! &lt;/div&gt;</pre> <p>(译注:依然无法应付复杂的翻译)</p> <h2>总结</h2> <p>本文论述了:</p> <ul> <li><strong>在测试用例中使用 <code>mocks </code> 以 mock 一个全局对象</strong></li> <li><strong>用 <code>config.mocks</code> 设置默认的 mock</strong></li> </ul> <p><em>原文链接:<a href="https://www.qdfuns.com/article.php?mod=view&amp;id=aaaddd492fb4c0f57287022a97293c7f&amp;uid=51352" rel="nofollow noreferrer">https://www.qdfuns.com/articl...</a></em></p>

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!