Dart单元测试:如何Mock内部API函数以测试目标函数
Dart异步函数单元测试:Mock内部API调用
要实现不调用真实API的单元测试,核心是让API依赖可替换,下面提供两种实用方案:
方案一:函数参数注入(轻量级,无需额外库)
先改造原函数,把API调用作为可选参数传入,这样测试时可以替换成模拟实现:
改造待测试函数
import 'package:test/test.dart'; // 真实API函数 Future<int> API() async { // 真实的API请求逻辑 return 0; } // 修改function,允许传入自定义的api函数 Future<int> function({Future<int> Function() api = API}) async { final int value = await api(); return value + 1; }
编写单元测试
测试时直接传入模拟的API函数,指定返回值:
void main() { test('当API返回1时,function应返回2', () { // 模拟API返回1 final mockApi = () async => 1; expect(function(api: mockApi), completion(equals(2))); }); test('当API返回5时,function应返回6', () { final mockApi = () async => 5; expect(function(api: mockApi), completion(equals(6))); }); }
方案二:用Mockito Mock类(适合复杂场景)
如果API逻辑复杂,建议将其封装成类,再用Mockito库来创建Mock对象,还能验证API方法的调用情况。
步骤1:封装API为类
class ApiService { Future<int> fetchValue() async { // 真实API请求逻辑 return 0; } } // 修改function,依赖ApiService类 Future<int> function(ApiService apiService) async { final int value = await apiService.fetchValue(); return value + 1; }
步骤2:添加依赖
在pubspec.yaml的dev_dependencies中添加:
dev_dependencies: test: any mockito: ^5.4.0 build_runner: ^2.4.4
步骤3:生成Mock类
创建mock_api_service.dart文件:
import 'package:mockito/mockito.dart'; import 'path/to/api_service.dart'; class MockApiService extends Mock implements ApiService {}
运行命令生成Mock代码:
dart run build_runner build
步骤4:编写测试
import 'package:test/test.dart'; import 'package:mockito/mockito.dart'; import 'mock_api_service.dart'; import 'path/to/function.dart'; void main() { late MockApiService mockApiService; // 每个测试前初始化Mock对象 setUp(() { mockApiService = MockApiService(); }); test('API返回1时,function返回2', () async { // 设定Mock方法的返回值 when(mockApiService.fetchValue()).thenAnswer((_) async => 1); // 调用待测试函数 final result = await function(mockApiService); // 验证结果正确 expect(result, equals(2)); // 验证API方法被调用了一次 verify(mockApiService.fetchValue()).called(1); }); }
关键说明
原代码的问题在于直接硬编码调用API(),没有预留替换入口,所以必须先改造代码让依赖可注入,这是实现可测试性的核心。
内容的提问来源于stack exchange,提问作者Yukinosuke Takada
相关产品推荐
相关产品推荐

