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的代码生成功能:
- 额外添加
build_runner依赖:
dev_dependencies: build_runner: ^2.4.0
- 在测试文件顶部添加注解:
import 'package:mockito/mockito.dart'; @GenerateMocks([File]) void main() { // ... 测试代码,直接使用生成的MockFile类即可 }
- 运行命令生成mock类:
dart run build_runner build
这样就能自动生成Mock类,不用手动编写啦。
内容的提问来源于stack exchange,提问作者pgirard
相关产品推荐
相关产品推荐

