You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中如何对文件保存读取功能进行单元测试

解决步骤

1. 先补充测试依赖

修改pubspec.yaml的dev_dependencies节点,新增路径提供工具的平台模拟依赖,用来解决单元测试环境下无法获取系统应用目录的问题:

dev_dependencies:
  flutter_test:
    sdk: flutter
  flutter_lints: ^1.0.0
  # 新增以下两个依赖
  path_provider_platform_interface: ^2.0.1
  plugin_platform_interface: ^2.0.2

2. 正确的单元测试实现

替换counter_test.dart的全部内容为以下代码,已经覆盖你提出的两个测试场景:

import 'package:flutter_test/flutter_test.dart';
import 'package:path_provider/path_provider.dart';
import 'package:path_provider_platform_interface/path_provider_platform_interface.dart';
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
import 'package:write_file_test/main.dart';
import 'dart:io';

// 模拟系统路径提供能力
class MockPathProvider extends Mock with PathProviderPlatform {
  final String testDir;
  MockPathProvider(this.testDir);

  @override
  Future<String?> getApplicationDocumentsPath() async {
    return testDir;
  }
}

void main() {
  late Directory tempDir;

  // 测试前置:创建临时目录模拟应用的私有存储目录
  setUpAll(() async {
    tempDir = await Directory.systemTemp.createTemp('counter_test');
    PathProviderPlatform.instance = MockPathProvider(tempDir.path);
  });

  // 测试后置:清理临时文件
  tearDownAll(() async {
    await tempDir.delete(recursive: true);
  });

  test('写入计数器功能正常', () async {
    final storage = CounterStorage();
    const testCounter = 6;
    // 等待异步写入完成,拿到返回的文件对象
    final writeResult = await storage.writeCounter(testCounter);
    // 可断言的内容1:返回的文件真实存在
    expect(await writeResult.exists(), isTrue);
    // 可断言的内容2:读取到的数值和写入的数值一致
    expect(await storage.readCounter(), testCounter);
  });

  test('模拟应用重启后存储数据不丢失', () async {
    // 用第一个实例写入测试值,模拟应用运行时的存储操作
    final beforeRestartStorage = CounterStorage();
    const testCounter = 12;
    await beforeRestartStorage.writeCounter(testCounter);
    // 重新实例化存储类,模拟应用重启后重新初始化存储模块的场景
    final afterRestartStorage = CounterStorage();
    // 断言:新实例读取到的值和之前写入的值一致,说明数据持久化正常
    expect(await afterRestartStorage.readCounter(), testCounter);
  });
}

问题对应说明

  • 关于writeCounter的返回值:它的返回类型是Future<File>,await后可以拿到写入完成的文件对象,可直接断言文件是否存在、文件内容是否符合预期,也可以通过配套的readCounter方法校验写入结果,后者更贴合业务逻辑的测试需求。
  • 关于模拟应用重启:只需要写入完成后重新创建CounterStorage实例即可,新实例对应应用重启后重新初始化的存储模块,底层文件是持久化保存在磁盘上的,不会因为类实例销毁而消失,只要新实例能读取到之前写入的值,就说明重启后数据不会丢失。

原测试代码的错误点

  1. 只声明了CounterStorage变量没有初始化,调用方法会直接抛空异常
  2. 没有await异步的writeCounter方法,直接拿到的是未完成的Future对象,无法校验结果
  3. 误用了Widget测试的find相关API,单元测试仅测业务逻辑,不需要渲染界面,不需要这类API

内容的提问来源于stack exchange,提问作者AndrewCSP

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 13:18:00