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

Dart中如何实现Ruby on Rails类实例Stub的等价操作?

在Dart中模拟File实例的方法调用(等价于Ruby on Rails的File.any_instance.expects(:delete))

要在Dart里实现类似Ruby on Rails中File.any_instance.expects(:delete)的测试效果,咱们得用Dart生态里的测试工具来模拟类的行为,最常用的就是mockito库。核心思路是通过依赖注入把File的创建逻辑抽离,这样测试时能替换成mock对象,进而验证方法调用。

步骤1:添加测试依赖

首先在pubspec.yaml里加上测试所需的依赖:

dev_dependencies:
  test: ^1.24.0
  mockito: ^5.4.0

步骤2:重构Storage类,支持依赖注入

原来的代码直接在方法里new File(path),这样没法替换成mock对象。咱们需要把File的创建逻辑通过构造函数注入:

import 'dart:io';

class Storage {
  final File Function(String path) fileFactory;

  // 构造函数注入文件工厂,默认使用原生File构造函数
  Storage({File Function(String path)? fileFactory}) 
      : fileFactory = fileFactory ?? (path) => File(path);

  // 修复原代码的async缺失问题
  Future<void> deleteFile(String path) async {
    var fileToDelete = fileFactory(path);
    if (await fileToDelete.exists()) {
      await fileToDelete.delete();
    }
  }
}

步骤3:编写测试代码,模拟File的行为

用mockito创建File的mock类,然后验证delete()方法是否被正确调用:

import 'package:mockito/mockito.dart';
import 'package:test/test.dart';
import 'dart:io';
import 'package:your_project_name/storage.dart'; // 替换成你的Storage文件路径

// 手动创建File的Mock类
class MockFile extends Mock implements File {}

void main() {
  group('Storage.deleteFile', () {
    test('调用delete()当文件存在时', () async {
      // 1. 创建MockFile实例
      final mockFile = MockFile();

      // 2. 设置mock的行为:exists()返回true
      when(mockFile.exists()).thenAnswer((_) async => true);
      // 设置delete()的空实现
      when(mockFile.delete()).thenAnswer((_) async => {});

      // 3. 创建Storage实例,注入返回mockFile的工厂函数
      final storage = Storage(
        fileFactory: (path) => mockFile,
      );

      // 4. 执行待测试方法
      await storage.deleteFile('/test/path');

      // 5. 验证方法调用:delete()被调用了1次
      verify(mockFile.delete()).called(1);
      // 顺便验证exists()也被调用了
      verify(mockFile.exists()).called(1);
    });

    test('文件不存在时不调用delete()', () async {
      final mockFile = MockFile();

      // 设置exists()返回false
      when(mockFile.exists()).thenAnswer((_) async => false);

      final storage = Storage(
        fileFactory: (path) => mockFile,
      );

      await storage.deleteFile('/test/path');

      // 验证delete()从未被调用
      verifyNever(mockFile.delete());
      verify(mockFile.exists()).called(1);
    });
  });
}

可选:用代码生成简化Mock类创建

如果不想手动写Mock类,可以用mockito的代码生成功能:

  1. 额外添加build_runner依赖:
dev_dependencies:
  build_runner: ^2.4.0
  1. 在测试文件顶部添加注解:
import 'package:mockito/mockito.dart';

@GenerateMocks([File])
void main() {
  // ... 测试代码,直接使用生成的MockFile类即可
}
  1. 运行命令生成mock类:
dart run build_runner build

这样就能自动生成Mock类,不用手动编写啦。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:44:29