Vue 组件单元测试深度探索:组件交互与状态变更 专业解析和实践

在这里插入图片描述

在Vue组件单元测试中,验证组件之间的交互(如父组件与子组件、兄弟组件之间的通信)以及状态变更的正确性对于保证整个应用的协调运作至关重要。本文详细介绍了父组件向子组件传递props、子组件向父组件发送事件、兄弟组件通过共享状态(如Vuex store)进行交互、兄弟组件通过事件总线(如this.$root.$emit)进行交互等组件交互与状态变更的测试详解与举例。

一、父组件与子组件交互

1. 父组件向子组件传递props

  • 原理:Vue提供了props特性,允许父组件以属性的方式将数据传递给子组件。
  • 用法
    • 在子组件中通过props选项定义需要接收的属性,如props: ['message', 'isActive']
    • 父组件模板中使用子组件时,直接将数据作为属性传入,如<ChildComponent message="Hello" :isActive="isChildActive" />。其中,:isActive="isChildActive"表示将父组件的isChildActive数据属性绑定到子组件的isActive prop。
    • 子组件内部可以直接访问这些props作为其自身数据的一部分。

测试父组件是否正确将props传递给子组件,并检查子组件是否根据props正确渲染:

import { shallowMount } from '@vue/test-utils';
import ParentComponent from '@/components/ParentComponent.vue';
import ChildComponent from '@/components/ChildComponent.vue';describe('ParentComponent', () => {let parentWrapper;let childWrapper;beforeEach(() => {parentWrapper = shallowMount(ParentComponent);childWrapper = parentWrapper.findComponent(ChildComponent);});afterEach(() => {parentWrapper.destroy();});it('passes props to child component', () => {expect(childWrapper.props()).toEqual({someProp: 'expectedValue',anotherProp: 42,});});it('updates child component when prop changes', async () => {parentWrapper.setProps({ someProp: 'updatedValue' });await parentWrapper.vm.$nextTick();expect(childWrapper.props('someProp')).toBe('updatedValue');});
});

2. 子组件向父组件发送事件

  • 原理:子组件通过$emit方法触发自定义事件,父组件监听并响应这些事件。
  • 用法
    • 在子组件内部,当需要向父组件发送信息时,使用this.$emit('eventName', eventData)触发一个自定义事件,如this.$emit('updateStatus', newStatus)
    • 父组件在使用子组件时,通过v-on@修饰符监听该事件,并在回调函数中处理传递的数据,如<ChildComponent @updateStatus="handleStatusUpdate" />。这里的handleStatusUpdate(newStatus)是父组件的方法,用于接收并处理子组件发出的事件数据。

测试子组件是否正确触发事件,并验证父组件是否正确接收并响应事件:

import { shallowMount } from '@vue/test-utils';
import ParentComponent from '@/components/ParentComponent.vue';
import ChildComponent from '@/components/ChildComponent.vue';describe('ParentComponent', () => {let parentWrapper;let childWrapper;beforeEach(() => {parentWrapper = shallowMount(ParentComponent);childWrapper = parentWrapper.findComponent(ChildComponent);});afterEach(() => {parentWrapper.destroy();});it('receives and handles event emitted by child component', async () => {const parentEventHandlerSpy = jest.spyOn(parentWrapper.vm, 'onChildEvent');childWrapper.vm.$emit('childEvent', { data: 'eventData' });await parentWrapper.vm.$nextTick();expect(parentEventHandlerSpy).toHaveBeenCalledWith({ data: 'eventData' });expect(parentWrapper.vm.someState).toBe('expectedStateAfterEvent');});
});

二、兄弟组件交互

1. 通过共享状态(如Vuex store)进行交互

  • 原理:Vuex是一个专为Vue应用设计的状态管理模式,它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
  • 用法
    • 首先,在项目中安装并配置Vuex。
    • 创建store文件夹,编写index.js文件,定义state、mutations、actions、getters等核心模块。
    • 在需要共享状态的兄弟组件中:
      • 通过mapStatemapGetters辅助函数将store中的状态或计算属性映射为局部计算属性。
      • 通过this.$store.commit('mutationName', payload)触发mutations更新状态。
      • 通过this.$store.dispatch('actionName', payload)触发异步操作或包含复杂逻辑的操作。
      • 兄弟组件间无需直接相互引用,只需对共享状态进行读取和修改,即可实现间接交互。

测试兄弟组件是否正确读取和修改共享状态,并根据状态变更正确更新自身:

import { createLocalVue, shallowMount } from '@vue/test-utils';
import Vuex from 'vuex';
import ComponentA from '@/components/ComponentA.vue';
import ComponentB from '@/components/ComponentB.vue';const localVue = createLocalVue();
localVue.use(Vuex);describe('ComponentA and ComponentB interaction via Vuex store', () => {let store;let componentAWrapper;let componentBWrapper;beforeEach(() => {store = new Vuex.Store({state: { sharedData: 'initialValue' },mutations: { updateSharedData(state, newValue) { state.sharedData = newValue; } },actions: { updateSharedDataAction(context, newValue) { context.commit('updateSharedData', newValue); } },});componentAWrapper = shallowMount(ComponentA, { localVue, store });componentBWrapper = shallowMount(ComponentB, { localVue, store });});afterEach(() => {componentAWrapper.destroy();componentBWrapper.destroy();});it('reads shared state correctly', () => {expect(componentAWrapper.vm.sharedData).toBe('initialValue');expect(componentBWrapper.vm.sharedData).toBe('initialValue');});it('updates shared state through actions/mutations and reacts to changes', async () => {componentAWrapper.vm.updateSharedData('newValue');await componentAWrapper.vm.$nextTick();await componentBWrapper.vm.$nextTick();expect(store.state.sharedData).toBe('newValue');expect(componentAWrapper.vm.sharedData).toBe('newValue');expect(componentBWrapper.vm.sharedData).toBe('newValue');});
});

2. 通过事件总线(如this.$root.$emit)进行交互

  • 原理:利用Vue实例的事件系统,通过一个公共的祖先组件(通常是根实例vm.$root)作为事件总线,使得兄弟组件间能够通过触发和监听全局事件进行通信。
  • 用法
    • 发送事件的兄弟组件使用this.$root.$emit('eventName', eventData)触发全局事件。
    • 接收事件的兄弟组件使用this.$root.$on('eventName', eventHandler)监听全局事件。当事件被触发时,eventHandler回调函数会被调用,处理传递的eventData

测试兄弟组件是否正确通过事件总线发送和接收事件,并据此更新自身状态:

import { shallowMount } from '@vue/test-utils';
import ComponentA from '@/components/ComponentA.vue';
import ComponentB from '@/components/ComponentB.vue';describe('ComponentA and ComponentB interaction via event bus', () => {let componentAWrapper;let componentBWrapper;beforeEach(() => {componentAWrapper = shallowMount(ComponentA);componentBWrapper = shallowMount(ComponentB);});afterEach(() => {componentAWrapper.destroy();componentBWrapper.destroy();});it('sends event from one component and receives it in another', async () => {const eventHandlerSpy = jest.spyOn(componentBWrapper.vm, 'onCustomEvent');componentAWrapper.vm.sendCustomEvent('eventData');await componentBWrapper.vm.$nextTick();expect(eventHandlerSpy).toHaveBeenCalledWith('eventData');expect(componentBWrapper.vm.someState).toBe('expectedStateAfterEvent');});
});

三、组件内部状态变更

测试组件在接收到用户输入、响应事件或执行内部逻辑时,其内部状态是否正确变更:

import { shallowMount } from '@vue/test-utils';
import MyComponent from '@/components/MyComponent.vue';describe('MyComponent', () => {let wrapper;beforeEach(() => {wrapper = shallowMount(MyComponent);});afterEach(() => {wrapper.destroy();});it('updates internal state on user input', async () => {const inputElement = wrapper.find('input[type="text"]');inputElement.setValue('newInputValue');await wrapper.vm.$nextTick();expect(wrapper.vm.internalState.inputValue).toBe('newInputValue');expect(wrapper.find('.displayed-value').text()).toBe('newInputValue');});it('changes state when an async action completes', async () => {const fetchMock = jest.fn().mockResolvedValue({ data: 'asyncData' });wrapper.setMethods({ fetchData: fetchMock });wrapper.vm.fetchData();await wrapper.vm.$nextTick();expect(fetchMock).toHaveBeenCalled();expect(wrapper.vm.internalState.asyncData).toBe('asyncData');});
});

更多组件单元测试《Vue 组件单元测试深度探索:细致解析与实战范例大全》

总结

通过对组件间的交互(包括父组件与子组件、兄弟组件之间的通信)以及组件内部状态变更进行详尽的单元测试,可以确保Vue应用中的组件能够协同工作,正确响应外部输入和内部逻辑,从而维持整个应用的稳定性和一致性。测试时应关注props传递、事件触发与接收、状态读取与更新等关键环节,确保在各种交互场景下组件行为符合预期。同时,利用测试工具提供的断言和模拟功能,使得测试用例既准确又易于维护。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/3964.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

自然语言处理 (NLP) 的技术演变史

一、简述 本文的目标是了解自然语言处理 (NLP) 的历史&#xff0c;包括 Transformer 体系结构如何彻底改变该领域并帮助我们创建大型语言模型 (LLM)。 基础模型&#xff08;如 GPT-4&#xff09;是最先进的自然语言处理模型&#xff0c;旨在理解、生成人类语言并与之交互。 要理…

鸿蒙小案例-搜索高亮

搜索高亮目前官方也没有可以现成的组件&#xff0c;但是需求来了&#xff0c;怎么办&#xff0c;只能摸索着自己写一个 目前官方API中最接近的应该是 richText组件了&#xff0c;富文本组件&#xff0c;当然可以实现&#xff0c;但是有不少问题 1.大小调整太麻烦&#xff0c;跟…

MySQL中截取字符串有哪些方法

文章目录 一、SUBSTRING() 或 SUBSTR() 函数二、LEFT() 函数三、RIGHT() 函数四、使用字符串连接和定位函数截取五、 正则表达式截取六、SUBSTRING_INDEX() 函数&#xff1a; 在MySQL中&#xff0c;你可以使用多种方法来截取字符串。以下是一些常用的方法&#xff1a; 一、SUB…

焊接机器人-常见焊接工艺参数

常见焊接工艺参数 常见焊缝平焊立焊 常见焊接工艺调试方法注意事项 常见焊缝 常见的焊缝一般见于不需要坡口焊的规则钢构件&#xff1a;如H型钢、H型牛角杠、T型梁、弧形梁等。 平焊 参数Value电流(安培)200A电压(伏特 )20V摆弧-振幅(毫米)4-6mm摆弧- 频率(Hz)1Hz摆弧- 两侧…

国产3D自研技术如何突围?眸瑞科技给3D建设、管理带来全新模式

眸瑞科技是全球领先的数字孪生引擎技术及服务提供商&#xff0c;它专注于让一切3D模型在全网多端轻量化处理与展示&#xff0c;为行业数字化转型升级与数字孪生应用提供成套的国产自研3D可视化技术、产品与服务。 引言 眸瑞科技是全球领先的数字孪生引擎技术及服务提供商&…

【MyBatisPlus】一、公共字段填充配置

目录 一、实体类配置 二、配置MyBatis Plus元对象处理器 三、接口字段自动填充 在使用mybatisplus项目中设置公共字段填充&#xff0c;可以按如下进行配置 一、实体类配置 TableField(value "create_time",fill FieldFill.INSERT)private LocalDateTime createTime…

【C++】哈希思想

目录 哈希介绍&#xff1a; 一&#xff0c;位图 1-1&#xff0c;位图的认识 1-2&#xff0c;位图的简单实现 1-3&#xff0c;位图的应用 二&#xff0c;布隆过滤器 2-1&#xff0c;布隆过滤器的认识 2-2&#xff0c;布隆过滤器的简单实现 2-3&#xff0c;布隆过滤器的…

Kafka 3.x.x 入门到精通(06)——Kafka进阶

Kafka 3.x.x 入门到精通&#xff08;06&#xff09;&#x1f449;&#x1f449;&#x1f449;&#x1f449; Kafka进阶 3. Kafka进阶3.1 Controller选举3.2 Broker上线下线3.3 数据偏移量定位3.4 Topic删除3.5 日志清理和压缩3.7 页缓存3.8 零拷贝3.9 顺写日志3.10 Linux集群部…

Debian12使用宝塔国际aaPanel无法安装Docker

宝塔国际aaPanel自带安装Docker&#xff0c;安装了几次都失败&#xff0c;最后仔细看了安装日志&#xff0c;才发现其中的问题。 复制 --2023-11-28 13:42:13-- https://node.aapanel.com/install/0/docker_install_en.sh Resolving node.aapanel.com (node.aapanel.com)...…

Dockerfile镜像构建实战

一、构建Apache镜像 cd /opt/ #建立工作目录 mkdir /opt/apache cd apache/vim Dockerfile #基于的基础镜像 FROM centos:7 #维护镜像的用户信息 MAINTAINER this is apache image <cyj> #镜像操作指令安装Apache软件 RUN yum install -y httpd #开启80端口 EXPOSE 80 #…

Java23种设计模式-行为型模式之解释器模式

解释器模式&#xff08;Interpreter Pattern&#xff09;&#xff1a;定义了一种文法&#xff0c;并且对于任何该文法的句子&#xff0c;都能够解释和执行。可以将复杂的问题分解成一系列简单的表达式&#xff0c;然后使用解释器来解释这些表达式。 涉及角色&#xff1a; 抽象…

从零开始利用MATLAB进行FPGA设计(五)详解双口RAM

创作于谱仪算法设计过程中的数字能谱生成模块设计。 往期回顾&#xff1a; 从零开始利用MATLAB进行FPGA设计&#xff08;四&#xff09;生成优化HDL代码 从零开始利用MATLAB进行FPGA设计&#xff08;三&#xff09;将Simulink模型转化为定点数据类型 目录 1.关于双口RAM …

php反序列化字符串逃逸

字符串逃逸 字符串逃逸是通过改变序列化字符串的长度造成的php反序列化漏洞 一般是因为替换函数使得字符串长度发生变化&#xff0c;不论变长还是变短&#xff0c;原理都大致相同 在学习之前&#xff0c;要先了解序列化字符串的结构&#xff0c;在了解结构的基础上才能更好理解…

JavaScript算法|前 K 个高频元素、寻找峰值和合并区间、 搜索二维矩阵 II和计算右侧小于当前元素的个数

文章目录 前 K 个高频元素方法一方法二代码 寻找峰值方法一 取最大值方法二 暴力法方法三 二分法 合并区间方法一 合并重叠方法二 合并重叠 搜索二维矩阵 II方法一 暴力法方法二 相邻比较法 计算右侧小于当前元素的个数方法一 暴力法方法二 排序法 前 K 个高频元素 给定一个非…

前端工程化详解

目录 开发前1.使用脚手架工具2.使用编译工具 开发中1.代码规范2.公共方法抽离3.公共组件抽离4.公共样式抽离5.icon 图片 国际化文案 常量等静态数据规划管理6.业务模块区分7.项目版本管理工具8.开发IDE以及代码检查工具 开发结束1.单元测试2.项目打包3.项目发布 开发前 1.使用…

低代码信创开发核心技术(四)动态元数据系统设计

一、概述 在当今快速发展的信息技术领域&#xff0c;动态元数据系统扮演着至关重要的角色。它不仅能够提供数据的描述信息&#xff0c;还能动态地适应业务需求的变化&#xff0c;从而提高系统的灵活性和可扩展性。构建一个动态元数据系统意味着我们可以在不重启系统的情况下&a…

【机器学习】机器学习学习笔记 - 监督学习 - KNN线性回归岭回归 - 02

监督学习 KNN (k-nearest neighbors) KNN 是用 k 个最近邻的训练数据集来寻找未知对象分类的一种算法 from sklearn import neighbors# 分类 # 创建KNN分类器模型并进行训练 classifier neighbors.KNeighborsClassifier(num_neighbors, weightsdistance) classifier.fit(X,…

前端面试题合集

1.对前端监控的理解&#xff1f; 异常监控&#xff08;监控前端页面的报错&#xff09;> try / catch 、window.onerror、window.addEventListener、Vue.config.errorHandle JS 代码运行错误、语法错误等&#xff1b;AJAX 请求错误&#xff1b;静态资源加载错误&#xff1…

硬件21、接线端子XH2.54、2.54排针排母、2510接插件、PH2.0、町洋接线端子5.08、ISP接口JTAG插座

XH2.54端子的间距为2.54毫米&#xff0c;2.54排针排母的间距也是2.54mm&#xff0c;2510接插件也是2.54、而PH2.0端子的间距为2.0毫米&#xff0c;町洋接线端子插针间的距离是5.08mm&#xff0c;ISP接口JTAG插座针脚的间距一般也是2.54mm XH2.54 针脚间距为2.54mm 插头 接线…

如何使用 Internet Download Manager (IDM) 来加速和优化你的下载体验 IDM 6.41下载神器

在当今信息爆炸的时代&#xff0c;下载文件和媒体内容已成为我们日常生活的一部分。无论是工作学习还是娱乐休闲&#xff0c;我们都需要从互联网上下载各种资源。为了提高下载效率和确保文件完整性&#xff0c;选择一款优秀的下载管理软件至关重要。Internet Download Manager …