如何对第一个Vue.js组件进行单元测试 (下)

简介: 包装我们断言的测试表示渲染一个类活动等于prop.grade的star列表。这是消费者的期望。当他们将数字传递给grade属性时,他们希望获得相同数量的活跃或选定的star。然而,在我们组件的逻辑中,活动类正是我们用来定义这个特征的东西。

我们的首次测试

       让我们来写首个测试。我们首先需要使用shallowMount手动挂载我们的组件,并将其存储在我们将执行断言的变量中。我们还可以通过propsData属性传递道具作为对象。

       已安装的组件是一个对象,它有一些实用方法:

屏幕快照 2018-10-31 下午7.13.02.png

       然后,我们可以写第一个断言:

屏幕快照 2018-10-31 下午7.13.20.png

       让我们来分析一下这里发生了什么。首先,我们使用Jest的expect函数,它将我们想要测试的值作为参数。在我们的例子中,在父级上用findAll方法来获取具有活动类的所有元素。这将返回一个WrapperArray,包含Wrappers数组的对象。

       一个WrapperArray有两个属性:父级(包含的Wrappers)和长度(Wrappers的数量)。后者是我们需要拥有预期数量的stars。

       expect函数还返回一个对象,我们可以在其上调用方法来测试传递的值。这些方法称为匹配器。在这里,我们使用toEqual匹配器并将其作为参数传递给期望值。该方法返回一个布尔值(boolean),这是测试通过或失败的原因。

       总而言之,在这里,我们期望在父级中找到的具有活动类的元素的总量应等于3(我们分配给等级道具的值)。

       在您的终端中,运行您的测试:

屏幕快照 2018-10-31 下午7.13.31.png

       你应该看到它通过。 

模拟用户输入

       Vue Test Utils可以轻松模拟真实用户最终在实际中所做的事情。在我们的用例中,用户可以点击stars来切换它们。我们可以在测试中使用触发器方法伪造它,并调度各种事件。

屏幕快照 2018-10-31 下午7.13.41.png

       在这里,我们首先用findAll获取第四颗star,它在传递的索引(从零开始的编号)中从WrapperArray返回一个Wrapper。然后,我们模拟它上面的点击事件- 我们模仿点击第四颗star的用户行为。

       由于我们将prop等级设置为3,因此在我们点击之前,第四个star应该处于非活动状态,因此click事件应该使其处于活动状态。在我们的代码中,这由一个活动类表示,我们仅在它们被激活时附加在star上。我们通过调用star上的classes方法来测试它,它将类名作为字符串数组返回。然后,我们使用toContain匹配器来确保活动类在这里。

设置和拆解

       由于我们触发了对组件的点击,我们已经改变了它的状态。问题是我们在所有测试中使用相同的组件。如果我们改变测试顺序并将其移到第一个位置会发生什么?然后第二次测试将失败。

       在测试时,你不想依赖诸如命令这样的脆弱的东西。测试套件应该是强大的,并且除非您破坏API,否则理想情况下现有测试应该不会改变。

       我们希望确保始终有一个可预测的父级来执行断言。我们可以通过设置和拆卸功能实现这一目标。这可以帮助我们在运行测试之前初始化,然后进行清理。

       在我们的例子中,有一种方法可以是在每次测试之前创建我们的父级并在之后销毁它。

屏幕快照 2018-10-31 下午7.13.59.png

       正如他们的名字所暗示的那样,beforeEach和afterEach分别在每次测试之前和之后运行。通过这种方式,我们可以100%确定每当我们运行新测试时,我们都能使用新的父级。

测试的特殊标识符

       将选择器与样式和其他目的(例如测试钩子)混合绝不是一个好主意。

       如果更改标签名称或类怎么办?

       如果您在要测试的元素上没有特定的标识符,例如计数器,该怎么办?

您不想使用无用的类污染您的生产代码。为测试提供专用钩子会更好,例如专用数据属性,但仅限于测试期间。这样就不会在最终构建中留下一团糟。

       处理此问题的一种方法是创建自定义Vue指令。

       Vue实例有一个指令方法,它接受两个参数- 一个名称,以及在DOM中注入时组件生命周期的钩子函数。如果您不关心特定的钩子,也可以传递单个函数。

       让我们在src /中创建一个名为directives的新目录,并添加一个test.js文件。我们将在我们的指令中导出我们想要传递的函数。

屏幕快照 2018-10-31 下午7.14.10.png

       一个指令钩子可以带几个参数,在我们的例子中,我们只需要前两个:el和binding。el参数引用指令绑定的元素。binding参数是一个对象,它包含我们在指令中传递的数据。这样我们就可以按照自己的意愿操纵元素。

屏幕快照 2018-10-31 下午7.14.23.png

       我们将一个对象传递给我们的指令,因此我们可以从data-test-开始生成数据属性。在处理函数中,我们绑定的每个属性,并在元素上设置一个基于名称和值的数据属性。

       我们将一个对象传递给我们的指令,因此我们可以从data-test-开始生成数据属性。在处理函数中,我们反复绑定每个binding属性,并在元素上设置一个基于名称和值的数据属性。

       现在我们需要注册我们的指令,以使用它。我们可以在全球范围内进行,但在我们的情况下,我们只会在本地注册- 就在我们的Rating.vue组件中。

屏幕快照 2018-10-31 下午7.14.38.png

       我们的指令现在可以在v-test名称下访问。尝试在计数器上设置以下指令:

屏幕快照 2018-10-31 下午7.14.47.png

       现在使用开发人员工具检查浏览器中的HTML。你的面板应该是这样的:

屏幕快照 2018-10-31 下午7.14.55.png

       开始工作了!现在,我们在开发模式和构建项目时都不需要这个。此数据属性的唯一目的是能够在测试期间定位元素,因此我们只想在运行它们时进行设置。为此,我们可以使用Webpack提供的NODE_ENV环境变量,这是为我们的项目提供动力的模块捆绑器。

       当我们运行测试时,NODE_ENV被设置为'test'。因此,我们可以使用它来确定何时设置测试属性。

屏幕快照 2018-10-31 下午7.15.06.png

       在浏览器中刷新您的应用并再次检查计数器:数据属性已消失。

       现在我们可以对我们需要定位的所有元素使用v-test指令。让我们从前面开始测试:

屏幕快照 2018-10-31 下午7.15.18.png

       我们用[data-test-id =“star”]替换了.star选择器,它允许我们在不破坏测试的情况下更改类以用于演示目的。这也是单一责任原则和松散耦合的好处之一 。

       我们是否还应该为我们测试的类使用这些钩子?

       在将此指令设置为要测试的目标元素之后,您可能想知道是否还应该使用它们来替换我们主动查找的类。让我们看看第一次测试的断言:

屏幕快照 2018-10-31 下午7.15.27.png

       我们应该对具有活动类的元素使用v-test,并在断言中替换选择器吗?好问题。

       单元测试都是关于一次测试一件事。it函数的第一个参数是一个字符串,我们用它来描述我们从消费者的角度做的事情。

       包装我们断言的测试表示渲染一个类活动等于prop.grade的star列表。这是消费者的期望。当他们将数字传递给grade属性时,他们希望获得相同数量的活跃或选定的star。然而,在我们组件的逻辑中,活动类正是我们用来定义这个特征的东西。我们根据具体情况进行分配,因此我们可以在视觉上区分活跃的stars。在这里,这个特定类的存在正是我们想要测试的。

       因此,在决定是否应该使用已有的选择器或设置v-test指令时,请问自己一个问题:我在测试什么,并且使用此选择器对业务逻辑透视图有意义吗?

它与功能或端到端测试有何不同?

       首先,单元测试组件可能看起来很奇怪。为什么要对UI和用户交互进行单元测试?这不是功能测试吗?

       在测试组件的公共API(也就是从消费者的角度来看)和从用户角度测试组件之间存在着根本但微妙的差异。首先,让我们强调一些重要的东西:我们正在测试定义良好的JavaScript函数,而不是UI。

       当您查看单个文件组件时,很容易忘记组件编译成JavaScript函数。我们没有测试底层的Vue机制,它从这个函数中导致了面向UI的副作用,比如在DOM中注入HTML。这就是Vue自己的测试已经解决的问题。在我们的例子中,我们的组件与任何其他函数没有区别:它接受输入并返回输出。这些原因和后果是我们正在测试的,而不是其他任何东西。

       令人困惑的是,我们的测试与常规单元测试略有不同。通常,我们写的东西如下:

屏幕快照 2018-10-31 下午7.15.35.png

       这里没有争论。输入和输出数据,这就是我们所关心的。对于组件,我们期望呈现视觉的东西。我们正在通过虚拟DOM并测试节点的存在。这也是您使用Selenium或Cypress.io等工具进行功能或端到端测试的方法。那有什么不同呢?

       通过单元测试,我们正在测试单独的行为。通过功能或端到端测试,我们正在测试场景。单元测试可确保程序单元的行为符合预期。它面向组件的消费者- 在软件中使用该组件的程序员。功能测试从用户角度确保功能或工作流的行为符合预期 。

本文转载自数据星河 www.bdgstore.com.cn

相关文章
|
3月前
|
JavaScript
在 Vue 中处理组件选项与 Mixin 选项冲突的详细解决方案
【10月更文挑战第18天】通过以上的分析和探讨,相信你对在 Vue 中使用 Mixin 时遇到组件选项与 Mixin 选项冲突的解决方法有了更深入的理解。在实际开发中,要根据具体情况灵活选择合适的解决方案,以确保代码的质量和可维护性。
140 7
|
2月前
|
缓存 JavaScript UED
Vue3中v-model在处理自定义组件双向数据绑定时有哪些注意事项?
在使用`v-model`处理自定义组件双向数据绑定时,要仔细考虑各种因素,确保数据的准确传递和更新,同时提供良好的用户体验和代码可维护性。通过合理的设计和注意事项的遵循,能够更好地发挥`v-model`的优势,实现高效的双向数据绑定效果。
167 64
|
30天前
|
数据采集 人工智能 自然语言处理
Midscene.js:AI 驱动的 UI 自动化测试框架,支持自然语言交互,生成可视化报告
Midscene.js 是一款基于 AI 技术的 UI 自动化测试框架,通过自然语言交互简化测试流程,支持动作执行、数据查询和页面断言,提供可视化报告,适用于多种应用场景。
278 1
Midscene.js:AI 驱动的 UI 自动化测试框架,支持自然语言交互,生成可视化报告
|
2月前
|
前端开发 JavaScript 测试技术
Vue3中v-model在处理自定义组件双向数据绑定时,如何避免循环引用?
Web 组件化是一种有效的开发方法,可以提高项目的质量、效率和可维护性。在实际项目中,要结合项目的具体情况,合理应用 Web 组件化的理念和技术,实现项目的成功实施和交付。通过不断地探索和实践,将 Web 组件化的优势充分发挥出来,为前端开发领域的发展做出贡献。
64 8
|
2月前
|
JavaScript
在 Vue 3 中,如何使用 v-model 来处理自定义组件的双向数据绑定?
需要注意的是,在实际开发中,根据具体的业务需求和组件设计,可能需要对上述步骤进行适当的调整和优化,以确保双向数据绑定的正确性和稳定性。同时,深入理解 Vue 3 的响应式机制和组件通信原理,将有助于更好地运用 `v-model` 实现自定义组件的双向数据绑定。
|
2月前
|
存储 JavaScript 开发者
Vue 组件间通信的最佳实践
本文总结了 Vue.js 中组件间通信的多种方法,包括 props、事件、Vuex 状态管理等,帮助开发者选择最适合项目需求的通信方式,提高开发效率和代码可维护性。
|
2月前
|
存储 JavaScript
Vue 组件间如何通信
Vue组件间通信是指在Vue应用中,不同组件之间传递数据和事件的方法。常用的方式有:props、自定义事件、$emit、$attrs、$refs、provide/inject、Vuex等。掌握这些方法可以实现父子组件、兄弟组件及跨级组件间的高效通信。
|
3月前
|
缓存 JavaScript UED
Vue 的动态组件与 keep-alive
【10月更文挑战第19天】总的来说,动态组件和 `keep-alive` 是 Vue.js 中非常实用的特性,它们为我们提供了更灵活和高效的组件管理方式,使我们能够更好地构建复杂的应用界面。深入理解和掌握它们,以便在实际开发中能够充分发挥它们的优势,提升我们的开发效率和应用性能。
60 18
|
2月前
|
机器学习/深度学习 自然语言处理 前端开发
前端神经网络入门:Brain.js - 详细介绍和对比不同的实现 - CNN、RNN、DNN、FFNN -无需准备环境打开浏览器即可测试运行-支持WebGPU加速
本文介绍了如何使用 JavaScript 神经网络库 **Brain.js** 实现不同类型的神经网络,包括前馈神经网络(FFNN)、深度神经网络(DNN)和循环神经网络(RNN)。通过简单的示例和代码,帮助前端开发者快速入门并理解神经网络的基本概念。文章还对比了各类神经网络的特点和适用场景,并简要介绍了卷积神经网络(CNN)的替代方案。
418 1
|
2月前
|
JavaScript 测试技术 API
Jest进阶:测试 Vue 组件
Jest进阶:测试 Vue 组件