使用 Jest 对 Vuex 模块进行单元测试
如果你正在构建一个中型到大型的 SPA,你很可能会遇到想要更好地处理 Vue 组件状态的情况。
在任何应用程序中,多个组件都依赖于同一个状态。让我们假设来自不同组件的多个动作想要改变相同的状态。为了克服这些挑战,Vuex帮助我们维护整个应用程序的状态。
在本文中,我将指导您在TypeScript 中实现一个 Vuex 模块,然后使用 Jest 对其进行单元测试。本教程的完整代码可在vuex-test GitHub 存储库中获得;随意分叉它。让我们开始吧!
-
什么是 Vuex?
-
创建一个 Vuex 模块
-
初始化测试
-
测试动作
-
测试吸气剂
-
测试突变
什么是 Vuex?
Vuex 是Vue 应用程序的状态管理模式和库,允许您在应用程序中使用集中状态管理,帮助您利用类似 Flux 的架构。Vuex store包含四个核心概念:
-
状态
-
吸气剂
-
突变
-
行动
状态对象包含您希望在存储中拥有的数据,包括您的所有应用程序级状态,作为唯一的事实来源。状态中定义的属性可以是任何数据类型,包括字符串、数字、对象或数组。
如果您想根据存储状态获得派生状态,例如,计算项目列表、过滤集合或在其他模块或组件中使用相同的派生状态集,您可以定义 getters。
另一方面,突变是我们改变状态的唯一方法。突变总是同步的,有效载荷是可选的。您可以通过提交,即MUTATION_NAME或payload. 始终建议从动作中调用突变。
动作可以执行异步操作并提交突变。动作处理程序接收一个上下文对象,该对象在存储实例上公开相同的方法或属性集。
您可以使用and来获取状态并调用突变。您可以使用和调用动作处理程序,它们是从商店中的其他动作调用的。context.getterscontext.state
context.commitaction-name
payload
Vuex 架构
创建一个 Vuex 模块
随着应用程序大小的增加,您的商店可能会变得臃肿。为了防止这种情况,Vuex 允许您将 store 拆分为 modules。每个模块都可以包含自己的状态、getter、突变和动作。
超过 20 万开发人员使用 LogRocket 来创造更好的数字体验了解更多 →
例如,让我们创建一个用于管理待办事项列表的应用程序。首先,新建一个待办事项模块,负责获取所有待办事项并根据需要更新状态。
我们的目标是为中大型应用程序构建模块,因此,最好将突变类型、称为函数的操作和模块实现拆分到单独的文件中:
-
mutation-types.ts: 包含所有函数名
-
actions.ts: 负责所有异步操作
-
index.ts: 模块实现
从“@/types/todo”导入 { IToDo }; { IToDo }来自“@/types/todo” ; 从'vuex-module-decorators'导入{Module,VuexModule,Mutation,Action};从'vuex-module-decorators'导入{模块,VuexModule ,突变,动作} ; 从 './actions' 导入 TodoActions;从'./actions'导入TodoActions ; 从 './mutation-types' 导入 * 作为突变类型;从'./mutation-types'导入*作为突变类型; @Module({namespaced: true, name: "Todos"})@Module ({ namespaced : true , name : "Todos" }) 导出类 ToDoModule 扩展 VuexModule {导出类ToDoModule扩展VuexModule { 待办事项:数组<IToDo> = [];:数组< IToDo > = []; 加载=假;=假; 完成待办事项(){完成待办事项(){ 返回 this.todos.filter((todo:IToDo)=> todo.completed);返回这个。待办事项。过滤器((待办事项:IToDo )=>待办事项。完成); }} @突变@突变 [mutationTypes.ON_FETCH_TODOS_STARTED]() {[突变类型。ON_FETCH_TODOS_STARTED ]() { this.loading = true;这个。加载=真; }} @突变@突变 \[mutationTypes.ON_FETCH_TODOS_SUCCESS\](数据:数组<IToDo>){. ON_FETCH_TODOS_SUCCESS\] (数据:数组< IToDo >){ this.loading = false;this.loading = false; this.todos = 数据;this.todos = data; }} @突变@Mutation [mutationTypes.ON_FETCH_TODOS_FAILED]() {[mutationTypes.ON_FETCH_TODOS_FAILED]() { this.loading = false;this.loading = false; 这.todos = [];this.todos = []; }} @Action({rawError: true})@Action({rawError: true}) 公共异步 fetchTodos():Promise<void> {public async fetchTodos():Promise<void> { 尝试 {try { this.context.commit(mutationTypes.ON_FETCH_TODOS_STARTED);this.context.commit(mutationTypes.ON_FETCH_TODOS_STARTED); 常量响应: Array<IToDo> = await TodoActions.fetchTodos();常量响应:数组< IToDo > =等待TodoActions 。fetchTodos (); this.context.commit(mutationTypes.ON_FETCH_TODOS_SUCCESS,响应);这个。上下文。提交(突变类型。ON_FETCH_TODOS_SUCCESS ,响应); } 捕捉(错误){}捕捉(错误){ this.context.commit(mutationTypes.ON_FETCH_TODOS_FAILED);这个。上下文。提交(突变类型。ON_FETCH_TODOS_FAILED ); }} }} }}
上面的代码片段包含以下实现:
-
fetchTodos Action:从 REST API 中获取待办事项并提交变更
-
ON_FETCH_TODOS_STARTED突变:更新loading状态属性
-
ON_FETCH_TODOS_SUCCESS突变:更新todos状态数组
-
ON_FETCH_TODOS_FAILED突变:重置todos和更新loading为假
-
completedTodosgetter:仅获取已完成的待办事项
初始化测试
我们将使用J est 框架进行单元测试;Jest 只是一个 JavaScript 测试框架,可以使用任何基于节点的包管理器(如 npm 或 Yarn)轻松安装。使用 Jest 的优势很少,例如,Jest 测试并行运行,包括内置代码覆盖,并支持隔离测试、模拟和快照测试。
您可以通过创建商店、将 Vuex 附加到 Vue 并注册商店来初始化测试。localVue是作用域的 Vue 构造函数,我们可以在不影响全局 Vue 构造函数的情况下对其进行更改。下面的代码片段将初始化商店:
描述('待办事项模块',函数(){( '待办事项模块' , function () { 让存储:任何;让存储:任何; 让 todosInstance: ToDoModule;让todosInstance : ToDoModule ; 之前(函数(){(函数() { localVue.use(Vuex);. 使用(Vuex ); store = new Vuex.Store({});=新的Vuex 。存储({}); 注册商店模块(商店);(商店); todosInstance = getModule(ToDoModule, store);= getModule ( ToDoModule , store ); });}); it('应该存在', function() {( '应该存在' , function () { 期望(todosInstance).toBeDefined();( todosInstance )。待定义(); });}); });});
测试动作
在todos模块中,我们创建了fetchTodos从 REST API 获取数据并使用突变填充状态的操作。由于 REST API 是一个外部调用,我们可以使用 Jest 函数模拟它,然后验证它是否被调用以及状态是否正在更新:
it('fetchTodos 动作应该填充 todos 状态', async function() {( 'fetchTodos 动作应该填充 todos 状态' , async function () { // 安排// 安排 const todosMocked = todos as Array<IToDo>;const todosMocked = todos as Array < IToDo >; // 行为// 行为 jest.spyOn(TodoActions, 'fetchTodos').mockImplementation(. spyOn ( TodoActions , 'fetchTodos' )。模拟实现( (): Promise<Array<IToDo>> => {(): Promise <数组< IToDo >> => { 返回 Promise.resolve(todosMocked);返回承诺。解决(todosMocked ); }} );); 等待 todosInstance.fetchTodos();等待todosInstance 。fetchTodos (); // 断言// 断言 期望(todosInstance.todos.length >0).toEqual(true);(todosInstance . todos .length > 0 )。toEqual (真); 期望(TodoActions.fetchTodos).toHaveBeenCalled();( TodoActions . fetchTodos )。toHaveBeenCalled (); });});
测试吸气剂
Getter 函数只返回状态对象。在我们的示例中,我们有一个 getter 函数,completedTodos它应该返回已完成的待办事项:
it('completedTodos getter 应该只返回已完成的 todos', async function() {( 'completedTodos getter 应该只返回已完成的 todos' , async function () { // 安排// 安排 const completedTodos = todosInstance.completedTodos;常量完成Todos = todosInstance 。已完成待办事项; // 断言// 断言 期望(completedTodos.every((todo:IToDo)=> todo.completed)).toEqual(true);( completedTodos . every (( todo : IToDo )=> todo . completed ))。toEqual (真); });});
喵影视TV高级版App,老牌影视盒子双播软件,内置80+线路!
测试突变
正如我们已经知道的,突变是改变状态的唯一方法。我们可以ON_FETCH_TODOS_SUCCESS通过发送模拟待办任务并验证状态是否被修改来测试突变。
下面的代码片段用于 success突变。这同样适用于startedanderror突变:
它('ON_FETCH_TODOS_SUCCESS 突变应该更新给定的待办事项',函数(){( 'ON_FETCH_TODOS_SUCCESS 突变应该更新给定的待办事项' , function () { // 安排// 安排 常量 todosTest = [常量todosTest = [ {{ 用户ID:13,: 13 , 编号:12,: 12 , title: "搬到新城市",: "搬到新城市" , 完成:假:假 },}, {{ 用户 ID:15,: 15 , 编号:21,: 21 , 标题:“完成一部小说”,:“完成一部小说” , 完成:真:真 },}, ];]; // 行为// 行为 todosInstance.ON_FETCH_TODOS_SUCCESS(todosTest);. ON_FETCH_TODOS_SUCCESS ( todosTest ); // 断言// 断言 期望(todosInstance.todos.length).toEqual(2);( todosInstance . todos .长度)。等于( 2 ); 期望(todosInstance.todos).toEqual(todosTest);( todosInstance . todos )。toEqual ( todosTest ); });});
结论
在本教程中,我们通过使用 TypeScript 和 Jest 创建和单元测试 Vuex 模块来了解 Vuex。我们介绍了 Vuex 存储的四个核心概念,包括状态、getter、突变和动作。借助 Vuex 的集中状态管理,您可以简化应用程序并利用类似 Flux 的架构。
我希望你学到了一些新东西,如果你有任何问题,一定要发表评论。快乐编码!
以用户的方式体验您的 Vue 应用程序
调试 Vue.js 应用程序可能很困难,尤其是在用户会话期间有数十个甚至数百个突变时。如果您对监控和跟踪生产中所有用户的 Vue 突变感兴趣,请尝试 LogRocket。LogRocket | Signup
LogRocket就像一个用于 Web 和移动应用程序的 DVR,从字面上记录您的 Vue 应用程序中发生的所有事情,包括网络请求、JavaScript 错误、性能问题等等。无需猜测问题发生的原因,您可以汇总并报告问题发生时应用程序所处的状态。
LogRocket Vuex 插件将 Vuex 突变记录到 LogRocket 控制台,为您提供有关导致错误的原因以及发生问题时应用程序处于什么状态的上下文。