在单元测试中使用Jest模拟VS Code extension API
对VS Code extension进行单元测试时通常会遇到一个问题,代码中所使用的VS Code编辑器的功能都依赖于vscode库,但是我们在单元测试中并没有添加对vscode库的依赖,所以导致运行单元测试时出错。由于vscode库是作为第三方依赖被引入到我们的VS Code extension中的,所以它并不受我们的控制,最好的办法就是在单元测试中对其中的API进行模拟。本文中我将介绍如何使用Jest来模拟vscode库的API。
如果你还不太熟悉如何开始创建一个VS Code extension,这里的文档可以教你快速上手。
创建好VS Code extension项目后,你会发现在根目录下有一个package.json文件,VS Code extension会从中读取配置项来管理UI界面元素,在实际开发中你可能会使用到其中的一些属性。我们可以通过package.json来设置项目所需要的依赖项,这里我们将Jest添加为dev dependency,并添加npm脚本以运行Jest单元测试。
npm i -D jest
{"scripts": {"test": "jest"}
}
模拟VS Code node module
Jest提供了一些mocking的选项,但是因为我们想要模拟整个vscode node module,所以最简单的办法是在与node_modules文件夹相同的位置(通常是项目的根目录)创建一个__mocks__文件夹,并在其中添加一个与要模拟的模块名称相同的文件(vscode.js)。
你不需要在测试代码中导入该模块,mock会自动加载它。Jest称此为manual mocks。
这种方法最大的好处是它能将我们的测试代码与所依赖的模块分离,使测试代码看起来更加整洁。这里有一个小问题,新加入的开发者需要知道__mocks__文件夹,否则很难理解单元测试是如何正常工作的,因为单元测试中并没有VS Code模块被模拟的代码。
以下就是对VS Code模块进行模拟的代码。我们并没有模拟整个API,你可以根据需要进行调整。
// vscode.jsconst languages = {createDiagnosticCollection: jest.fn()
};const StatusBarAlignment = {};const window = {createStatusBarItem: jest.fn(() => ({show: jest.fn()})),showErrorMessage: jest.fn(),showWarningMessage: jest.fn(),createTextEditorDecorationType: jest.fn()
};const workspace = {getConfiguration: jest.fn(),workspaceFolders: [],onDidSaveTextDocument: jest.fn()
};const OverviewRulerLane = {Left: null
};const Uri = {file: f => f,parse: jest.fn()
};
const Range = jest.fn();
const Diagnostic = jest.fn();
const DiagnosticSeverity = { Error: 0, Warning: 1, Information: 2, Hint: 3 };const debug = {onDidTerminateDebugSession: jest.fn(),startDebugging: jest.fn()
};const commands = {executeCommand: jest.fn()
};const vscode = {languages,StatusBarAlignment,window,workspace,OverviewRulerLane,Uri,Range,Diagnostic,DiagnosticSeverity,debug,commands
};module.exports = vscode;
使用模拟的VS Code模块的示例
我的开源项目Git Mob for VS code中使用了这种方法,我将用其中的代码来说明如何使用模拟的VS Code模块。
下面的例子中,VS Code编辑器的状态栏会根据Git钩子prepare-commit-msg是否被调用来做相应的调整,你可以看到这里我并没有将vscode模块导入到我的测试文件中并对其进行模拟。
// git-mob-hook-status.spec.jsconst { hasPrepareCommitMsgTemplate } = require("../prepare-commit-msg-file");
const { gitMobHookStatus } = require("./git-mob-hook-status");jest.mock("./../prepare-commit-msg-file");describe("Hook or template status", function() {let mockContext;beforeAll(function() {mockContext = {subscriptions: []};});afterEach(function() {hasPrepareCommitMsgTemplate.mockReset();});it("using git template for co-authors", () => {hasPrepareCommitMsgTemplate.mockReturnValue(false);const statusBar = gitMobHookStatus({ context: mockContext })();expect(statusBar).toEqual(expect.objectContaining({text: "$(file-code) Git Mob",tooltip: "Using .gitmessage template"}));});it("using git prepare commit msg for co-authors", () => {hasPrepareCommitMsgTemplate.mockReturnValue(true);const statusBar = gitMobHookStatus({ context: mockContext })();expect(statusBar).toEqual(expect.objectContaining({text: "$(zap) Git Mob",tooltip: "Using prepare-commit-msg hook"}));});
});
// git-mob-hook-status.js
const vscode = require("vscode");
const { hasPrepareCommitMsgTemplate } = require("../prepare-commit-msg-file");function gitMobHookStatus({ context }) {const myStatusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left,10);context.subscriptions.push(myStatusBarItem);return function() {myStatusBarItem.text = "$(file-code) Git Mob";myStatusBarItem.tooltip = "Using .gitmessage template";if (hasPrepareCommitMsgTemplate()) {myStatusBarItem.text = "$(zap) Git Mob";myStatusBarItem.tooltip = "Using prepare-commit-msg hook";}myStatusBarItem.show();return myStatusBarItem;};
}exports.gitMobHookStatus = gitMobHookStatus;
你可以在这里查看源代码:
- git-mob-hook-status.spec.js
- git-mob-hook-status.js
我能检查vscode模块中的方法是否被调用了吗?
你可以导入模拟的vscode模块。下面的代码中,我想要检查当用户修改co-author文件时onDidSaveTextDocument事件是否被订阅了。
const vscode = require("../__mocks__/vscode");// ...
test("Reload co-author list when git-coauthors file saved", () => {reloadOnSave(coAuthorProviderStub);expect(vscode.workspace.onDidSaveTextDocument).toHaveBeenCalledWith(expect.any(Function));// ...
});
// ...
可以看到这里都是Jest mock API的标准用法,这意味着我们可以在代码中正常使用vscode模块的方法,而不受manual mock的任何限制。例如,我们还可以使用mockImplementation来修改实现。
更多示例可以查看这里的源代码:
- reload-on-save.spec.js
编写单元测试最大的好处是可以快速得到反馈结果,如果你对TDD(Test-Driven Development,测试驱动开发)情有独钟,那么单元测试将使你对VS Code extension的开发更加信心满满。
资料获取方法
【留言777】


各位想获取源码等教程资料的朋友请点赞 + 评论 + 收藏,三连!
三连之后我会在评论区挨个私信发给你们~
相关文章:
在单元测试中使用Jest模拟VS Code extension API
对VS Code extension进行单元测试时通常会遇到一个问题,代码中所使用的VS Code编辑器的功能都依赖于vscode库,但是我们在单元测试中并没有添加对vscode库的依赖,所以导致运行单元测试时出错。由于vscode库是作为第三方依赖被引入到我们的VS C…...
django boostrap html实现可拖拽的左右布局,鼠标拖动调整左右布局的大小或占比
一、实现的效果 最近需要在Django项目中,实现一个左右布局的html页面,页面框架使用的是boostrap。但这个布局不是简单的左右分栏布局,而是需要实现可以通过鼠标拖拽的方式动态调整左右两侧布局的大小和占比。效果大致如下: 一开始,页面分为左右两块布局: 鼠标放到中间的…...
谈谈闭包和闭包使用场景
一、什么是闭包 概念:闭包还是作用域的一种特殊应用 二、触发闭包的情况 1.函数当做返回值被返回 2.函数当做参数被传递 3.自执行匿名函数 //情况1:函数当做返回值被返回 function fn(){const a 1;return function(){console.log(a) //1}; } const a …...
MATLAB算法实战应用案例精讲-【图像处理】边界框锚框
目录 目标检测 应用场景 目标检测发展历程 常用数据集 边界框(bounding box)...
04什么场景要用到微服务
一句话导读 根据微服务的特点,可以总结为在构建复杂的、大型的、分布式的、高可用、高并发、高性能的应用时可以使用微服务架构。 目录 一句话导读 一、微服务适用场景 1.业务复杂,模块多且相对独立 2.团队多,管理隔离 3.应用规模大&#…...
.NET SqlSuger 简单介绍,超快开发数据库
文章目录 前言SqlSugar使用我的环境Nuget 安装新建连接串DB First 和 Code First使用增删改查 总结 前言 我之前介绍过EFCore 怎么使用Nuget快速创建数据库,我之后发现SqlSugar更快。这里简单再说一下SqlSugar如何使用 .NET Core 数据库DB First自动生成࿰…...
SpringBoot复习:(28)【前后端不分离】自定义View
一、自定义View package cn.edu.tju.view;import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.stereotype.Comp…...
springcloud3 springcloud stream的学习以及案例(了解)
一 springcloud stream的作用 1.1 springcloud stream作用 stream屏蔽底层消息中间件的差异,降低切换成本,统一消息的编程模型。 stream中的消息通信模式遵循了“发布-订阅”模式。 1.2 Binder作用 通过定义绑定器Binder作为中间层,实现…...
Kotlin理解内置函数
目录 一 内置函数1.1 apply 函数1.2 let 函数1.3 run函数1.4 with函数1.5 also函数1.6 takeIf函数1.7 takeUnless函数1.8 总结 Kotlin内置函数包括:let、run、with、apply、also,这些函数都是在Any类中定义的扩展函数,所以任何对象都可以调用…...
手机app测试
一、安装、卸载、更新、运行 1.安装、卸载 应用是否可以正常安装(命令行安装;apk/ipa安装包安装)(有网,无网是否都正常)卸载过程中出现死机,断电,重启等意外的情况&…...
Centos部署Git
Centos部署Git 文章目录 Centos部署Git部署步骤初始化配置免登录 部署步骤 初始化 -- 安装git yum install git配置免登录 配置git下载代码时 每次都需要输入密码的事情 -- 生成 gitconfig 文件 git config --global credential.helper store -- 配置登录邮箱 git config …...
k8s 控制器
Kubernetes(K8S)是一种开源的容器编排平台,它可以自动化地管理容器化应用程序的部署、扩展和运行。K8S中的控制器是一种重要的组件,它可以确保应用程序的状态与期望的状态一致。在K8S中,有五种常见的控制器,…...
谷歌关闭跨域限制.(生成一个开发浏览器),Chrome关闭跨域
(一)、首先找到浏览器在电脑磁盘中的位置,并复制 (二)、复制一个浏览器的快捷方式到桌面(不影响正常浏览器) (三)、chrom鼠标右键属性,修改快捷方式的目标 (四)chrome.exe 后面添加 --disable-web-security --user-data-dir 复制的Chrome浏览…...
实践指南-前端性能提升 270% | 京东云技术团队
一、背景 当我们疲于开发一个接一个的需求时,很容易忘记去关注网站的性能,到了某一个节点,猛地发现,随着越来越多代码的堆积,网站变得越来越慢。 本文就是从这样的一个背景出发,着手优化网站的前端性能&a…...
8月11日上课内容 nginx的多实例和动静分离
多实例部署 在一台服务器上有多个tomcat的服务。 配置多实例之前,看单个实例是否访问正常。 1.安装好 jdk 2.安装 tomcat cd /opt tar zxvf apache-tomcat-9.0.16.tar.gz mkdir /usr/local/tomcat mv apache-tomcat-9.0.16 /usr/local/tomcat/tomcat1 cp -a /usr…...
腾讯云CVM服务器端口在安全组中打开!
腾讯云服务器CVM端口怎么开通?腾讯云服务器端口是通过配置安全组规则来开通的,腾讯云服务器网以开通80端口为例来详细说下腾讯云轻量应用服务器开启端口的方法,其他的端口的开通如8080、1433、443、3306、8888等端口也适用于此方法࿰…...
k8s、docker添加daemon.json添加“exec-opts“: [“native.cgroupdriver=systemd“]后无法启动的问题
考虑k8s下docker下载镜像太慢,修改了daemon.json,按照手册抄,添加 {"exec-opts": ["native.cgroupdriversystemd"],"registry-mirrors": ["https://kn0t2bca.mirror.aliyuncs.com"] }结果发现k8s起…...
React组件性能优化实践
React组件性能优化最佳实践 React组件性能优化的核心是减少渲染真实DOM节点的频率,减少 Virtual DOM比对的频率。 组件卸载前进行清理操作 在组件中为 window注册的全局事件,以及定时器,在组件卸载前要清理掉,防止组件卸载后继…...
SpringBoot复习:(29)静态资源的配置路径
WebMvcAutoConfiguration 首页处理:...
mysql延时问题排查
背景介绍 最近遇到一个奇怪的问题,有个业务,每天早上七点半产生主从延时,延时时间12.6K; 期间没有抽数/备份等任务;查看慢日志发现,期间有一个delete任务,在主库执行了161s delete from xxxx_…...
基于数字孪生的水厂可视化平台建设:架构与实践
分享大纲: 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年,数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段,基于数字孪生的水厂可视化平台的…...
C++ 基础特性深度解析
目录 引言 一、命名空间(namespace) C 中的命名空间 与 C 语言的对比 二、缺省参数 C 中的缺省参数 与 C 语言的对比 三、引用(reference) C 中的引用 与 C 语言的对比 四、inline(内联函数…...
蓝桥杯3498 01串的熵
问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798, 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...
Pinocchio 库详解及其在足式机器人上的应用
Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库,专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性,并提供了一个通用的框架&…...
论文笔记——相干体技术在裂缝预测中的应用研究
目录 相关地震知识补充地震数据的认识地震几何属性 相干体算法定义基本原理第一代相干体技术:基于互相关的相干体技术(Correlation)第二代相干体技术:基于相似的相干体技术(Semblance)基于多道相似的相干体…...
智能AI电话机器人系统的识别能力现状与发展水平
一、引言 随着人工智能技术的飞速发展,AI电话机器人系统已经从简单的自动应答工具演变为具备复杂交互能力的智能助手。这类系统结合了语音识别、自然语言处理、情感计算和机器学习等多项前沿技术,在客户服务、营销推广、信息查询等领域发挥着越来越重要…...
排序算法总结(C++)
目录 一、稳定性二、排序算法选择、冒泡、插入排序归并排序随机快速排序堆排序基数排序计数排序 三、总结 一、稳定性 排序算法的稳定性是指:同样大小的样本 **(同样大小的数据)**在排序之后不会改变原始的相对次序。 稳定性对基础类型对象…...
虚拟电厂发展三大趋势:市场化、技术主导、车网互联
市场化:从政策驱动到多元盈利 政策全面赋能 2025年4月,国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》,首次明确虚拟电厂为“独立市场主体”,提出硬性目标:2027年全国调节能力≥2000万千瓦࿰…...
Python 实现 Web 静态服务器(HTTP 协议)
目录 一、在本地启动 HTTP 服务器1. Windows 下安装 node.js1)下载安装包2)配置环境变量3)安装镜像4)node.js 的常用命令 2. 安装 http-server 服务3. 使用 http-server 开启服务1)使用 http-server2)详解 …...
LOOI机器人的技术实现解析:从手势识别到边缘检测
LOOI机器人作为一款创新的AI硬件产品,通过将智能手机转变为具有情感交互能力的桌面机器人,展示了前沿AI技术与传统硬件设计的完美结合。作为AI与玩具领域的专家,我将全面解析LOOI的技术实现架构,特别是其手势识别、物体识别和环境…...
