脚本宝典收集整理的这篇文章主要介绍了

Vue单元测试—Karma+Mocha+Chai实践

脚本宝典小编觉得挺不错的,现在分享给大家,也给大家做个参考,希望能帮助你少写一行代码,多一份安全和惬意。
<p><code></p> <p>本文基于vue-webpack-boilerplate。官方推荐使用Karma+Mocha+Chai来进行单元测试。</p> <h2 id="articleHeader0">介绍</h2> <p><strong>Karma</strong>:一个测试运行器,用于启动浏览器,运行测试案例并将结果报告给我们。该工具的主要作用是将项目运行在各种主流Web浏览器进行测试。</p> <p><strong>Mocha</strong>:一个测试框架。可结合chai断言库使用。</p> <p><strong>Chai</strong>:一个测试断言库,提供了更好的断言语法。所谓断言,就是对组件做一些操作,并预言产生的结果。如果测试结果与断言相同则测试通过。Chai断言库中,to be been is that which and has have with at of same but does这些语言链是没有意义的,只是便于理解而已。</p> <ul> <li> <p><a href="http://chaijs.com/api/bdd/" rel="nofollow noreferrer" target="_blank">BDD英文文档</a></p> </li> <li> <p><a href="http://www.jianshu.com/p/f200a75a15d2" rel="nofollow noreferrer" target="_blank">中文文档</a></p> </li> </ul> <h2 id="articleHeader1">实践</h2> <h3 id="articleHeader2">组件无依赖,无props</h3> <p>对于无需导入任何依赖,也没有props的,直接编写测试案例即可。</p> <p><strong>MyComponent.vue</strong></p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="<template><br /> <span>{{ message }}</span><br /> </template><br /> <script> <a href="http://www.js-code.com/tag/export" title="export" target="_blank">export</a> default { data () { return { message: 'hello!' } }, created () { <a href="http://www.js-code.com/tag/this" title="this" target="_blank">this</a>.message = 'bye!' } } </script>" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs xml"><code><span class="hljs-tag">&lt;<span class="hljs-name">template</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>{{ message }}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript"> <span class="hljs-keyword"><a href="http://www.js-code.com/tag/export" title="浏览关于“export”的文章" target="_blank" class="tag_link">export</a></span> <span class="hljs-keyword">default</span> { data () { <span class="hljs-keyword">return</span> { <span class="hljs-attr">message</span>: <span class="hljs-string">'hello!'</span> } }, created () { <span class="hljs-keyword"><a href="http://www.js-code.com/tag/this" title="浏览关于“this”的文章" target="_blank" class="tag_link">this</a></span>.message = <span class="hljs-string">'bye!'</span> } } </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span></code></pre> <p><strong>MyComponent.spec.js</strong></p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="// 导入 Vue.js 和组件,进行测试 import Vue from 'vue' import MyComponent from 'path/to/MyComponent.vue' describe('MyComponent', () => {<br /> // 检查原始组件选项<br /> it('has a created hook', () => {<br /> expect(typeof MyComponent.created).to.eql('function')<br /> })<br /> })<br /> " title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs typescript"><code><span class="hljs-comment">// 导入 <a href="http://www.js-code.com/tag/vue" title="浏览关于“Vue”的文章" target="_blank" class="tag_link">Vue</a>.js 和组件,进行测试</span> <span class="hljs-keyword">import</span> Vue <span class="hljs-keyword">from</span> <span class="hljs-string">'vue'</span> <span class="hljs-keyword">import</span> MyComponent <span class="hljs-keyword">from</span> <span class="hljs-string">'path/to/MyComponent.vue'</span> describe(<span class="hljs-string">'MyComponent'</span>, <span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> { <span class="hljs-comment">// 检查原始组件选项</span> it(<span class="hljs-string">'has a created hook'</span>, <span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> { expect(<span class="hljs-keyword">typeof</span> MyComponent.created).to.eql(<span class="hljs-string">'function'</span>) }) }) </code></pre> <h3 id="articleHeader3">组件有props</h3> <p>对于组件需要props,编写单元测试时,通过<code>propsData</code>传递该参数。</p> <p><strong>MyComponent.vue</strong></p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="<template></p> <p>{{ msg }}</p> <p></template><br /> <script> <a href="http://www.js-code.com/tag/export" title="export" target="_blank">export</a> default { props: ['msg'] } </script>" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs xml"><code><span class="hljs-tag">&lt;<span class="hljs-name">template</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{{ msg }}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript"> <span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> { <span class="hljs-attr">props</span>: [<span class="hljs-string">'msg'</span>] } </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span></code></pre> <p><strong>MyComponent.spec.js</strong></p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="import Vue from 'vue' import MyComponent from 'path/to/MyComponent.vue' function getRenderedText (Component, propsDataMsg) { const Ctor = Vue.extend(Component) const vm = new Ctor({ propsData: propsDataMsg}).$mount() return vm.$el.textContent } describe('MyComponent', () => {<br /> it('renders correctly with different props', () => {<br /> expect(getRenderedText(MyComponent, {<br /> msg: 'Hello'<br /> })).to.eql('Hello')<br /> expect(getRenderedText(MyComponent, {<br /> msg: 'Bye'<br /> })).to.eql('Bye')<br /> })<br /> })" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs typescript"><code><span class="hljs-keyword">import</span> Vue <span class="hljs-keyword">from</span> <span class="hljs-string">'vue'</span> <span class="hljs-keyword">import</span> MyComponent <span class="hljs-keyword">from</span> <span class="hljs-string">'path/to/MyComponent.vue'</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getRenderedText</span> (<span class="hljs-params">Component, propsDataMsg</span>) </span>{ <span class="hljs-keyword"><a href="http://www.js-code.com/tag/const" title="浏览关于“const”的文章" target="_blank" class="tag_link">const</a></span> Ctor = Vue.extend(Component) <span class="hljs-keyword">const</span> vm = <span class="hljs-keyword">new</span> Ctor({ propsData: propsDataMsg}).$mount() <span class="hljs-keyword">return</span> vm.$el.textContent } describe(<span class="hljs-string">'MyComponent'</span>, <span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> { it(<span class="hljs-string">'renders correctly with different props'</span>, <span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> { expect(getRenderedText(MyComponent, { msg: <span class="hljs-string">'Hello'</span> })).to.eql(<span class="hljs-string">'Hello'</span>) expect(getRenderedText(MyComponent, { msg: <span class="hljs-string">'Bye'</span> })).to.eql(<span class="hljs-string">'Bye'</span>) }) })</code></pre> <h3 id="articleHeader4">组件有依赖</h3> <p>若组件存在依赖,则可通过inject-loader解决。inject-loader可将任意依赖项注入到*.vue组件中。</p> <p><strong>MyComponent.vue</strong></p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="<template></p> <div class=&quot;msg&quot;>{{ msg }}</div> <p></template></p> <p><script> // <a href="http://www.js-code.com/tag/this" title="this" target="_blank">this</a> dependency needs to be mocked import SomeService from '../service'</p> <p>export default { data () { return { msg: SomeService.msg } } } </script>" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs xml"><code><span class="hljs-tag">&lt;<span class="hljs-name">template</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name"><a href="http://www.js-code.com/tag/div" title="浏览关于“div”的文章" target="_blank" class="tag_link">div</a></span> <span class="hljs-attr">class</span>=<span class="hljs-string">"msg"</span>&gt;</span>{{ msg }}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript"> <span class="hljs-comment">// this dependency needs to be mocked</span> <span class="hljs-keyword">import</span> SomeService <span class="hljs-keyword">from</span> <span class="hljs-string">'../service'</span> <span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> { data () { <span class="hljs-keyword">return</span> { <span class="hljs-attr">msg</span>: SomeService.msg } } } </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span></code></pre> <p><strong>MyComponent.spec.js</strong></p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="//“!!”表示禁用全局配置的所有loaders。“vue-loader?inject!”表示使用vue-loader,传入inject参数。 const ExampleInjector = require('!!vue-loader?inject!./example.vue') //运行ExampleInjector函数返回一个MyComponent的实例,该实例中MyComponent组件的依赖项已被模拟。 const ExampleWithMocks = ExampleInjector({ // mock it '../service': { msg: 'Hello from a mocked service!' } }) describe('MyComponent', () => {<br /> it('should render', () => {<br /> <a href="http://www.js-code.com/tag/const" title="const" target="_blank">const</a> vm = new <a href="http://www.js-code.com/tag/vue" title="Vue" target="_blank">Vue</a>({<br /> template: '</p> <div><test></test></div> <p>',<br /> components: {<br /> 'test': ExampleWithMocks<br /> }<br /> }).$mount()<br /> expect(vm.$el.querySelector('.msg').textContent).to.eql('Hello from a mocked service!')<br /> })<br /> })" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs typescript"><code><span class="hljs-comment">//“!!”表示禁用全局配置的所有loaders。“vue-loader?inject!”表示使用vue-loader,传入inject参数。</span> <span class="hljs-keyword">const</span> ExampleInjector = <span class="hljs-built_in">require</span>(<span class="hljs-string">'!!vue-loader?inject!./example.vue'</span>) <span class="hljs-comment">//运行ExampleInjector函数返回一个MyComponent的实例,该实例中MyComponent组件的依赖项已被模拟。</span> <span class="hljs-keyword">const</span> ExampleWithMocks = ExampleInjector({ <span class="hljs-comment">// mock it</span> <span class="hljs-string">'../service'</span>: { msg: <span class="hljs-string">'Hello from a mocked service!'</span> } }) describe(<span class="hljs-string">'MyComponent'</span>, <span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> { it(<span class="hljs-string">'should render'</span>, <span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> { <span class="hljs-keyword">const</span> vm = <span class="hljs-keyword">new</span> Vue({ template: <span class="hljs-string">'&lt;div&gt;&lt;test&gt;&lt;/test&gt;&lt;/div&gt;'</span>, components: { <span class="hljs-string">'test'</span>: ExampleWithMocks } }).$mount() expect(vm.$el.querySelector(<span class="hljs-string">'.msg'</span>).textContent).to.eql(<span class="hljs-string">'Hello from a mocked service!'</span>) }) })</code></pre> <h3 id="articleHeader5">异步操作</h3> <p>对于异步操作,it块执行的时候,需要传入一个回调函数,通常该函数被命名为done。当测试结束的时候,必须显式调用这个函数,告诉Mocha测试结束了。否则,Mocha就无法知道,测试是否结束,会一直等到超时报错。</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="// 在状态更新后检查生成的 HTML it('updates the rendered message when vm.message updates', done => {<br /> const vm = new Vue(MyComponent).$mount()<br /> vm.message = 'foo'<br /> // 在状态改变后和断言 DOM 更新前等待一刻<br /> Vue.nextTick(() => {<br /> expect(vm.$el.textContent).to.eql('foo')<br /> done()<br /> })<br /> })" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs typescript"><code><span class="hljs-comment">// 在状态更新后检查生成的 <a href="http://www.js-code.com/tag/html" title="浏览关于“HTML”的文章" target="_blank" class="tag_link">HTML</a></span> it(<span class="hljs-string">'updates the rendered message when vm.message updates'</span>, <span class="hljs-function"><span class="hljs-params">done</span> =&gt;</span> { <span class="hljs-keyword">const</span> vm = <span class="hljs-keyword">new</span> Vue(MyComponent).$mount() vm.message = <span class="hljs-string">'foo'</span> <span class="hljs-comment">// 在状态改变后和断言 <a href="http://www.js-code.com/tag/dom" title="浏览关于“DOM”的文章" target="_blank" class="tag_link">DOM</a> 更新前等待一刻</span> Vue.nextTick(<span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> { expect(vm.$el.textContent).to.eql(<span class="hljs-string">'foo'</span>) done() }) })</code></pre> <h2 id="articleHeader6">npm run unit</h2> <p>执行 npm run unit 命令运行单元测试。会产生结果列表:</p> <p><span class="img-wrap"><img data-src="/img/bVUlfF?w=640&amp;h=413" src="https://static.segmentfault.com/v-5cc2cd8e/global/img/squares.svg" alt="clipboard.png" title="clipboard.png" style="cursor: pointer;"></span></p> <p>若想看测试覆盖率等情况,可在test/unit/coverage查看。</p> <h2 id="articleHeader7">注意</h2> <ul> <li> <p>测试脚本都放在 test/unit/specs/ 目录下。</p> </li> <li> <p>脚本命名方式是[组件名].spec.js。</p> </li> <li> <p>在karma.conf.js文件里修改karma配置。</p> </li> <li> <p>单元测试默认测试 src 目录下除了 main.js 之外的所有文件,可在 test/unit/index.js 文件中修改。</p> </li> <li> <p>测试脚本里面应该包括一个或多个describe块,每个describe块应该包括一个或多个it块。</p> <ul> <li> <p>describe块称为"测试套件"(test suite),表示一组相关的测试。它是一个函数,第一个参数是测试套件的名称("加法函数的测试"),第二个参数是一个实际执行的函数。</p> </li> <li> <p>it块称为"测试用例"(test case),表示一个单独的测试,是测试的最小单位。它也是一个函数,第一个参数是测试用例的名称("1 加 1 应该等于 2"),第二个参数是一个实际执行的函数。</p> </li> </ul> </li> <li> <p>Mocha在describe块之中,提供测试用例的四个钩子:before()、after()、beforeEach()和afterEach()。它们会在指定时间执行。</p> </li> </ul> <p>参考:<br /><a href="https://cn.vuejs.org/v2/guide/unit-testing.html" rel="nofollow noreferrer" target="_blank">单元测试</a><br /><a href="https://vue-loader.vuejs.org/en/workflow/testing-with-mocks.html" rel="nofollow noreferrer" target="_blank">Testing with Mocks</a><br /><a href="https://vuejs-templates.github.io/webpack/unit.html" rel="nofollow noreferrer" target="_blank">Unit Testing</a><br /><a href="http://www.ruanyifeng.com/blog/2015/12/a-mocha-tutorial-of-examples.html" rel="nofollow noreferrer" target="_blank">测试框架 Mocha 实例教程</a><br /><a href="http://chaijs.com/api/bdd/" rel="nofollow noreferrer" target="_blank">Chai</a></p> <p></code></p>

总结

以上是脚本宝典为你收集整理的

Vue单元测试—Karma+Mocha+Chai实践

全部内容,希望文章能够帮你解决

Vue单元测试—Karma+Mocha+Chai实践

所遇到的程序开发问题,欢迎加入QQ群277859234一起讨论学习。如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典网站推荐给程序员好友。 本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。

80%的人都看过