NEWS DETAIL

AtomGit Flutter 鸿蒙客户端:MoodStorage 的 CRUD 集成验证

发布时间:2026/10/26 8:38:32 · 栏目:资讯中心

尧图网络原创建站知识分享正文
前两篇分别覆盖了模型单元测试和 Widget 组件测试。现在进入测试金字塔的中间层——数据层集成测试。E-Brufen 使用 Hive CE 作为本地存储引擎MoodStorage封装了完整的 CRUD 操作。本文将演示如何为一个基于 Hive 的 ChangeNotifier 编写可靠的集成测试。1. 测试数据层的挑战测试数据层与测试纯逻辑有很大不同挑战说明测试隔离每次测试需要独立的数据库实例互不干扰环境差异鸿蒙真机、模拟器、PC 上的文件系统不同异步操作Hive 的openBox、put、delete都是异步的副作用notifyListeners()产生副作用需验证但不阻塞E-Brufen 的解决方案是使用临时目录 setUp/tearDown 生命周期管理。2. MoodStorage 架构回顾在进入测试之前先回顾被测对象。MoodStorage是一个ChangeNotifier内部使用 Hive Box 存储 JSON 序列化的情绪记录classMoodStorageextendsChangeNotifier{staticconst_boxNamemoods;Box?_box;int _nextId1;Futurevoidinit()async{_boxawaitHive.openBox(_boxName);if(_box!.isNotEmpty){_nextId_box!.keys.foldint(0,(max,k)...)1;}}Futureintinsert(MoodEntryentry)async{...}ListMoodEntrygetAll(){...}ListMoodEntrygetByDate(DateTimedate){...}ListMoodEntrygetByWeek(DateTimeanyDay){...}Futurevoidupdate(int id,MoodEntryupdated)async{...}Futurevoiddelete(int id)async{...}Mapint,intgetWeeklyMoodCounts(DateTimeanyDay){...}}注意getAll、getByDate、getByWeek是同步方法——它们从内存中的_box直接读取。而insert、update、delete是异步的因为它们涉及 Hive 的磁盘写入。3. 测试基础设施setUp 和 tearDown每次测试都需要一个全新的、干净的 Hive 实例。我们利用setUp创建临时目录和初始化存储用tearDown清理importdart:io;importpackage:flutter_test/flutter_test.dart;importpackage:hive_ce/hive_ce.dart;importpackage:firstproject/data/mood_storage.dart;importpackage:firstproject/models/mood_entry.dart;voidmain(){lateMoodStoragestorage;setUp(()async{finaltmpDirDirectory.systemTemp.createTempSync(ebrufen_test_);Hive.init(tmpDir.path);storageMoodStorage();awaitstorage.init();});tearDown(()async{storage.dispose();});几个关键设计决策createTempSync(ebrufen_test_)每次测试创建一个独立的临时目录前缀ebrufen_test_便于识别和手动清理。Hive.init(tmpDir.path)必须显式调用因为测试环境没有Hive.initFlutter()所需的 Flutter 平台支持。storage.dispose()关闭 Hive Box释放文件句柄。如果忘了调用后续测试可能因为文件锁冲突而失败。4. 插入和查询测试这是最基础的数据流验证——写一条记录再读出来test(insert and retrieve a mood entry,()async{finalnowDateTime.now();finalidawaitstorage.insert(MoodEntry(moodType:MoodType.happy,note:今天很开心,createdAt:now,updatedAt:now,));expect(id,greaterThan(0));finalallstorage.getAll();expect(all.length,1);expect(all.first.moodType,MoodType.happy);expect(all.first.note,今天很开心);});验证顺序断言id 0——自增 ID 从 1 开始断言列表长度为 1断言字段内容与写入一致不必验证 ID 等于具体值如expect(id, 1)因为如果多个测试共享同一个 Hive 实例ID 会累积。使用greaterThan(0)更稳健。5. 日期过滤测试getByDate根据日期过滤记录——这是日记应用最常用的查询test(getByDate filters correctly,()async{finaltodayDateTime.now();finalyesterdaytoday.subtract(constDuration(days:1));awaitstorage.insert(MoodEntry(moodType:MoodType.happy,note:today,createdAt:today,updatedAt:today));awaitstorage.insert(MoodEntry(moodType:MoodType.sad,note:yesterday,createdAt:yesterday,updatedAt:yesterday));finaltodayMoodsstorage.getByDate(today);expect(todayMoods.length,1);expect(todayMoods.first.note,today);});这个测试验证了插入两条跨日期的记录后getByDate(today)只返回今天的 1 条note字段确实匹配的是 “today” 而不是 “yesterday”getByDate的内部实现使用DateTime(year, month, day)构造当天零点配合add(Duration(days: 1))构造次日零点实现范围查询。如果时区处理有误在跨时区环境中可能漏掉记录——这是集成测试的价值所在。6. 更新和删除测试更新和删除都需要验证修改是否真正持久化test(update mood entry,()async{finalnowDateTime.now();finalidawaitstorage.insert(MoodEntry(moodType:MoodType.tired,createdAt:now,updatedAt:now));awaitstorage.update(id,MoodEntry(moodType:MoodType.happy,createdAt:now,updatedAt:DateTime.now()));finalallstorage.getAll();expect(all.first.moodType,MoodType.happy);});test(delete mood entry,()async{finalnowDateTime.now();finalidawaitstorage.insert(MoodEntry(moodType:MoodType.angry,createdAt:now,updatedAt:now));awaitstorage.delete(id);finalallstorage.getAll();expect(all.length,0);});两个测试的共同模式先插入再更新/删除最后重新读取验证。这种先写后读的模式模拟了真实用户操作流程。7. 统计查询测试getWeeklyMoodCounts返回本周每种情绪的计数——这是情绪图表的数据源test(getWeeklyMoodCounts returns counts for a week,()async{finalmondayDateTime(2026,7,6);for(vari0;i5;i){finalmoodVals[MoodType.happy,MoodType.happy,MoodType.tired,MoodType.sad,MoodType.happy];awaitstorage.insert(MoodEntry(moodType:moodVals[i],createdAt:monday.add(Duration(days:i)),updatedAt:monday.add(Duration(days:i)),));}finalcountsstorage.getWeeklyMoodCounts(monday);expect(counts[5],3);// happy 3expect(counts[3],1);// tired 1expect(counts[2],1);// sad 1});这里使用固定日期DateTime(2026, 7, 6)而非DateTime.now()——因为后者在不同时间运行会产生不同结果测试就不稳定了。8. ChangeNotifier 通知验证MoodStorage继承自ChangeNotifier每次insert、update、delete后都会调用notifyListeners()。我们可以验证这一点test(notifyListeners is called on insert,()async{varnotifiedfalse;storage.addListener(()notifiedtrue);awaitstorage.insert(MoodEntry(moodType:MoodType.calm,createdAt:DateTime.now(),updatedAt:DateTime.now(),));expect(notified,true);});9. 测试数据库 vs 生产数据库在 E-Brufen 的测试中我们使用了与生产相同的 Hive CE 实现但通过Directory.systemTemp隔离了数据文件维度测试环境生产环境初始化Hive.init(tmpDir.path)Hive.initFlutter()with fallback数据目录systemTemp/ebrufen_test_xxxx应用文档目录Box 名称moods相同moods相同数据持久化随 tearDown 销毁持久化到应用生命周期这种实现相同、路径隔离的策略保证了测试的环境相关性——如果 Hive CE 在鸿蒙上有兼容性问题测试也能捕获。提示E-Brufen 的main.dart中生产环境 Hive 初始化有降级逻辑Hive.initFlutter()失败时回退到Hive.init(Directory.systemTemp.path)这个设计与测试使用 systemTemp 的路径一致。10. 运行与调试# 运行所有数据层测试fluttertesttest/data/database_test.dart# 运行并显示详细输出fluttertesttest/data/database_test.dart--reporterexpanded# 运行特定测试fluttertest--plain-nameinsert and retrievetest/data/database_test.dart总结E-Brufen 的database_test.dart包含 5 个测试用例插入查询、日期过滤、更新、删除、周统计。通过setUp/tearDown管理测试隔离使用临时目录避免污染真实调用 Hive CE API 保证了测试的参考价值。下一篇我们将转向错误处理看看 E-Brufen 如何在鸿蒙环境下实现优雅降级。上一篇Widget 测试实战验证情绪选择器与首页卡片下一篇Flutter 鸿蒙应用错误处理与优雅降级策略E-Brufen Dev, Flutter 鸿蒙开发者项目地址AtomGit - E‑Brufen
✦

本文为尧图网络原创建站知识分享。想针对自身行业获取定制化建站方案?欢迎咨询,资深顾问免费为你出思路。

RELATED

相关 资讯推荐

MORE

更多 新鲜资讯

JMeter入门实战:从零构建HTTP接口性能测试脚本与结果分析
2026/10/26 17:54:34

JMeter入门实战:从零构建HTTP接口性能测试脚本与结果分析

1. 项目概述:从零开始,用JMeter搞定HTTP性能测试 刚接触性能测试的新手,或者是从功能测试转过来的朋友,一听到“压测”两个字,心里可能就有点发怵。工具那么多,概念那么杂,从哪儿下手呢&#xf…

Earendel: 一个纯TS写的POSIX兼容的微内核Web操作系统
2026/10/25 22:00:41

Earendel: 一个纯TS写的POSIX兼容的微内核Web操作系统

最近我用TypeScript写了一个运行在浏览器里的Web操作系统 Earendel(目前已知的距离地球最遥远的恒星)。开发它的初衷主要是为了Linux和操作系统课程的教学。市面上绝大多数Web OS项目,要么只是做了一个长得像Windows/macOS的网页UI拼盘&#…

5分钟掌握Windows防撤回神器:让微信QQ撤回消息无处遁形[特殊字符]
2026/10/25 8:02:16

5分钟掌握Windows防撤回神器:让微信QQ撤回消息无处遁形[特殊字符]

5分钟掌握Windows防撤回神器:让微信QQ撤回消息无处遁形🚀 【免费下载链接】RevokeMsgPatcher :trollface: A hex editor for WeChat/QQ/TIM - PC版微信/QQ/TIM防撤回补丁(我已经看到了,撤回也没用了) 项目地址: http…

从零制作同人动画:技术路线、流程与实战避坑指南
2026/10/25 15:27:07

从零制作同人动画:技术路线、流程与实战避坑指南

1. 先搞清楚这个“粉丝动画”到底是什么,以及它能解决什么问题看到“五条悟VS宿傩/咒术回战粉丝动画”这个标题,很多人的第一反应可能是去找一个现成的视频。但如果你是一个想自己动手创作、或者想了解这类作品背后技术流程的创作者,这个标题…

闭源降价80%,开源却在涨价:AI定价的交叉路口
2026/10/25 22:24:04

闭源降价80%,开源却在涨价:AI定价的交叉路口

8月6日,两条价格曲线悄然交汇。 一条向下:OpenAI把GPT-5.6 Luna的输出价格从6美元砍到1.2美元/百万Token,降幅80%。另一条向上:同一天,DeepSeek公告全线涨价,措辞是"涨幅较大",非试探…

产线三防平板选哪个牌子?5个品牌实测告诉你别瞎买
2026/10/25 8:02:07

产线三防平板选哪个牌子?5个品牌实测告诉你别瞎买

产线三防平板选哪个牌子?5个品牌实测告诉你别瞎买经常有工厂朋友拿着网上的"三防平板十大品牌排行榜"来问我:到底选哪个?说实话排行榜看看就行,真正选型得看你产线什么场景。今天挑五个在产线数字化里用得比较多的品牌—…

看完这篇,还想了解更多?

预约尧图网络顾问一对一沟通,针对你的行业与现状给出建站建议,全程免费。

免费咨询