Flutter Secure Storage单元测试空类型匹配及空检查错误如何解决
问题原因及修复方案
核心问题
- 你的
Authentication类内部硬编码初始化了FlutterSecureStorage实例,没有对外提供依赖注入入口,测试时你创建的MockFlutterSecureStorage实例从未被实际调用,所有打桩逻辑完全不生效。 - 测试运行时实际调用的是真实的
FlutterSecureStorage实例,测试环境无对应的存储值,返回的null触发了类型不匹配、空安全相关报错。 - 保存token的测试用例中,打桩时传入的
value参数和业务代码实际写入的值不匹配,也会导致打桩失效。
修复步骤
第一步:改造Authentication类支持依赖注入
构造函数新增可选的secureStorage参数,默认使用真实的FlutterSecureStorage实例,不影响原有线上业务逻辑,测试时可传入Mock实例替换:
class Authentication { final FlutterSecureStorage _secureStorage; static const String BEARER_TOKEN = 'BEARER_TOKEN'; Authentication({FlutterSecureStorage? secureStorage}) : _secureStorage = secureStorage ?? const FlutterSecureStorage(); Future<OAuthToken> setToken(OAuthTokenResponse token) async { assert(token.accessToken != null, "A non null token is required"); final String jsonToken = json.encode(token.toJson()); await _secureStorage.write(key: BEARER_TOKEN, value: jsonToken); return token; } Future<OAuthToken?> getToken() async { final String? jsonToken = await _secureStorage.read(key: BEARER_TOKEN); if (jsonToken == null) { return null; } return OAuthToken(json.decode(jsonToken)); } Future<void> deleteToken() async { await _secureStorage.delete(key: BEARER_TOKEN); } }
第二步:修改测试代码注入Mock实例
初始化Authentication时传入你创建的MockFlutterSecureStorage实例,让打桩逻辑生效;同时统一write操作的参数匹配规则,避免打桩失效:
void main() { final MockFlutterSecureStorage mockSecureStorage = MockFlutterSecureStorage(); // 注入Mock实例替换真实存储类 final Authentication dataSource = Authentication(secureStorage: mockSecureStorage); final token = OAuthToken.fromJson(json.decode(fixture('oauth_token_response.json'))); group('getToken', () { test('should return OAuthToken from FlutterSecureStorage when there is one the saved', () async { // arrange when(() => mockSecureStorage.read(key: BEARER_TOKEN)).thenAnswer((_) async => fixture('oauth_token_response.json')); // act final result = await dataSource.getToken(); //assert verify(() => mockSecureStorage.read(key: BEARER_TOKEN)).called(1); expect(result, equals(token)); }); test('should return null when is not saved token', () async { // arrange when(() => mockSecureStorage.read(key: BEARER_TOKEN)).thenAnswer((_) async => null); // act final result = await dataSource.getToken(); //assert verify(() => mockSecureStorage.read(key: BEARER_TOKEN)).called(1); expect(result, isNull); }); }); group('saveToken', () { test('should call FlutterSecureStorage to save token', () async { // arrange final expectedJsonString = json.encode(token.toJson()); when(() => mockSecureStorage.write(key: BEARER_TOKEN, value: expectedJsonString)).thenAnswer((invocation) => Future<void>.value()); //act await dataSource.setToken(token); // assert verify(() => mockSecureStorage.write(key: BEARER_TOKEN, value: expectedJsonString)).called(1); }); }); }
内容的提问来源于stack exchange,提问作者user11820495
相关产品推荐
相关产品推荐

