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

Dart集成测试中DatabaseManagerMock的存放位置与注入方案问询

解决方案:手动覆盖依赖+测试目录实现测试数据库管理器

步骤1:在test目录下创建测试专用的DatabaseManager实现

不用Mock,而是编写基于sqflite_ffi的内存数据库实现,放在test/utils/test_database_manager.dart:

import 'package:sqflite/sqflite.dart';
import 'package:sqflite_ffi/sqflite_ffi.dart';
import '../lib/path/to/database_manager.dart'; // 导入抽象类

class TestDatabaseManager implements DatabaseManager {
  late Database _db;

  @override
  Future<void> init() async {
    // 初始化sqflite_ffi
    sqfliteFfiInit();
    _db = await databaseFactoryFfi.openDatabase(
      inMemoryDatabasePath,
      options: OpenDatabaseOptions(
        onCreate: (db, version) {
          // 执行和生产环境一致的建表语句
          return db.execute('CREATE TABLE ...');
        },
        version: 1,
      ),
    );
    // 填充测试初始化数据
    await _insertTestData();
  }

  // 实现DatabaseManager的所有抽象方法,直接操作内存数据库
  @override
  Future<List<SomeModel>> getSomeData() async {
    final List<Map<String, dynamic>> maps = await _db.query('some_table');
    return List.generate(maps.length, (i) => SomeModel.fromMap(maps[i]));
  }

  Future<void> _insertTestData() async {
    // 插入测试用数据
    await _db.insert('some_table', {'name': 'test data'});
  }

  @override
  Future<void> close() async => _db.close();
}

步骤2:在测试中手动覆盖依赖

无需生成第二个injectable配置,测试初始化时先加载主项目依赖,再覆盖DatabaseManager的实现:

import 'package:get_it/get_it.dart';
import 'package:injectable/injectable.dart';
import 'package:test/test.dart';
import '../lib/injection.dart'; // 导入主项目的injectable配置
import 'utils/test_database_manager.dart';

void main() {
  late GetIt getIt;

  setUp(() async {
    // 初始化主项目依赖
    getIt = GetIt.instance;
    await configureDependencies(Environment.prod); // 替换为你使用的环境标识

    // 覆盖已注册的DatabaseManager为测试实现
    getIt.registerLazySingleton<DatabaseManager>(
      () => TestDatabaseManager(),
      override: true, // 允许覆盖已注册类型
    );

    // 初始化测试数据库
    await getIt<DatabaseManager>().init();
  });

  tearDown(() async {
    // 测试结束后关闭数据库并重置GetIt
    await getIt<DatabaseManager>().close();
    await getIt.reset();
  });

  test('测试依赖DatabaseManager的业务流程', () async {
    final someClass = getIt<SomeClass>();
    final result = await someClass.doSomething();
    expect(result, equals('预期结果'));
  });
}

处理depend_on_referenced_packages警告

由于sqflite_ffi是dev依赖,测试目录代码导入它会触发警告,可在项目根目录的analysis_options.yaml中添加规则忽略:

linter:
  rules:
    - depend_on_referenced_packages:
        exclude:
          - test/**/*.dart

方案优势

  • 测试代码完全隔离在test目录,不污染生产代码
  • 跳过injectable多配置生成的路径问题,实现更简洁
  • 测试用DatabaseManager是真实实现,更适配集成测试对数据库交互逻辑的验证需求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 08:32:31