如何用Mocktail Mock EasyLocalization的BuildContext扩展方法?
如何用Mocktail正确Mock easy_localization的BuildContext扩展方法
easy_localization为BuildContext提供了如下扩展方法:
Locale get deviceLocale => EasyLocalization.of(this)!.deviceLocale;
我尝试用Mocktail Mock这个方法,写了以下测试代码:
import 'package:mocktail/mocktail.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:test/test.dart'; class MockBuildContext extends Mock implements BuildContext {} void main() { test("Sample test", () { final context = MockBuildContext(); when(() => context.deviceLocale).thenReturn(const Locale('en', 'US')); expect(Locale('en', 'US'), context.deviceLocale); }); }
运行时却报错:type 'Locale' is not a subtype of type '_EasyLocalizationProvider?',推测是因为Mock扩展方法失败,实际调用了原方法导致的。请问如何正确Mock该扩展方法以达到预期效果?
解决方法
因为扩展方法本质是静态语法糖,无法直接Mock。正确思路是MockEasyLocalization.of(context)返回的实例,而非直接Mock扩展方法。
完整可运行的测试代码如下:
import 'package:mocktail/mocktail.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:test/test.dart'; import 'package:flutter/widgets.dart'; // 创建Mock类模拟EasyLocalization实例 class MockEasyLocalization extends Mock implements EasyLocalization {} class MockBuildContext extends Mock implements BuildContext {} void main() { setUpAll(() { // 注册Mock类型,避免类型不匹配问题 registerFallbackValue(MockBuildContext()); }); test("正确Mock deviceLocale", () { final context = MockBuildContext(); final mockEasyLoc = MockEasyLocalization(); // 第一步:Mock EasyLocalization.of(context)返回我们的Mock实例 when(() => EasyLocalization.of(context)).thenReturn(mockEasyLoc); // 第二步:Mock Mock实例的deviceLocale属性 when(() => mockEasyLoc.deviceLocale).thenReturn(const Locale('en', 'US')); // 此时调用context.deviceLocale会走Mock逻辑 expect(context.deviceLocale, const Locale('en', 'US')); }); }
原理说明
扩展方法context.deviceLocale本质是调用EasyLocalization.of(context)!.deviceLocale,它不属于BuildContext的成员,只是一种静态语法包装。直接Mock扩展方法行不通,必须从根源入手:先让EasyLocalization.of(context)返回我们的Mock实例,再Mock该实例的deviceLocale属性,这样调用扩展方法时就会触发Mock逻辑。
内容的提问来源于stack exchange,提问作者Rudy
相关产品推荐
相关产品推荐

