【发布时间】:2021-12-08 16:04:50
【问题描述】:
有类似的问题询问相同的错误(例如here),但它们的原因是由于不正确的模拟。就我而言,我似乎正确地模拟了该方法,但是当我在启用 All Exceptions 的 Visual Studio Code 中进行调试时,我得到了运行时异常:
_TypeError (type 'Null' is not a subtype of type 'Future<AuthenticationToken?>')
如果我在异常之后继续测试(或者只是在禁用 All Exceptions 的情况下调试测试,或者只是在不调试的情况下运行它们),我的所有测试都可以通过。
dependencies:
hive: ^2.0.4
hive_flutter: ^1.1.0
dev_dependencies:
mocktail: ^0.1.4
import 'package:hive/hive.dart';
class AuthenticationRepository {
static const _currentTokenKey = 'key';
AuthenticationToken? _inMemoryToken;
Future<Box<AuthenticationToken?>> _tokenBox;
...
Future<AuthenticationToken?> activeToken() async =>
_inMemoryToken ?? (await _tokenBox).get(_currentTokenKey);
...
}
示例测试文件:
import 'package:app/src/data/authentication/repository.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';
class MockAuthenticationRepository extends Mock
implements AuthenticationRepository {}
void main() {
AuthenticationRepository authenticationRepository;
SUT sut; // SUT depends on AuthenticationRepository
setUp(() {
authenticationRepository = MockAuthenticationRepository();
when(() => authenticationRepository.activeToken())
.thenAnswer((realInvocation) => Future.value(AuthenticationToken()));
sut = SUT(authenticationRepository);
});
test('some test', () async {
await sut.someMethod();
verify(() => authenticationRepository.activeToken()).called(1);
});
}
这是堆栈跟踪:
MockAuthenticationRepository.activeToken (/Users/davilin/Documents/Projects/app/flutter/app/lib/src/data/authentication/repository.dart:296)
main.initMocks.<anonymous closure> (/Users/davilin/Documents/Projects/app/flutter/app/test/network/token_refresh_interceptor_test.dart:33)
when.<anonymous closure> (/Users/davilin/.pub-cache/hosted/pub.dartlang.org/mocktail-0.1.4/lib/src/mocktail.dart:211)
main.initMocks (/Users/davilin/Documents/Projects/app/flutter/app/test/network/token_refresh_interceptor_test.dart:33)
main.<anonymous closure>.<anonymous closure> (/Users/davilin/Documents/Projects/app/flutter/app/test/network/token_refresh_interceptor_test.dart:52)
Declarer._runSetUps.<anonymous closure> (/Users/davilin/.pub-cache/hosted/pub.dartlang.org/test_api-0.4.2/lib/src/backend/declarer.dart:329)
Future.forEach.<anonymous closure> (dart:async/future.dart:495)
Future.doWhile.<anonymous closure> (dart:async/future.dart:535)
StackZoneSpecification._registerUnaryCallback.<anonymous closure>.<anonymous closure> (/Users/davilin/.pub-cache/hosted/pub.dartlang.org/stack_trace-1.10.0/lib/src/stack_zone_specification.dart:126)
StackZoneSpecification._run (/Users/davilin/.pub-cache/hosted/pub.dartlang.org/stack_trace-1.10.0/lib/src/stack_zone_specification.dart:208)
StackZoneSpecification._registerUnaryCallback.<anonymous closure> (/Users/davilin/.pub-cache/hosted/pub.dartlang.org/stack_trace-1.10.0/lib/src/stack_zone_specification.dart:126)
_rootRunUnary (dart:async/zone.dart:1436)
_CustomZone.runUnary (dart:async/zone.dart:1335)
_CustomZone.runUnaryGuarded (dart:async/zone.dart:1244)
_CustomZone.bindUnaryCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1281)
Future.doWhile (dart:async/future.dart:551)
Future.forEach (dart:async/future.dart:493)
Declarer._runSetUps (/Users/davilin/.pub-cache/hosted/pub.dartlang.org/test_api-0.4.2/lib/src/backend/declarer.dart:329)
<asynchronous gap> (Unknown Source:0)
StackZoneSpecification._registerUnaryCallback.<anonymous closure> (/Users/davilin/.pub-cache/hosted/pub.dartlang.org/stack_trace-1.10.0/lib/src/stack_zone_specification.dart:0)
<asynchronous gap> (Unknown Source:0)
我只是想记录一下,以防有人能解释为什么会发生这种情况。
【问题讨论】:
-
你可以分享这个功能吗? .get(_currentTokenKey)?
-
@pedropimont 是的,它来自 hive (2.0.4),box.dart。源代码在这里:github.com/hivedb/hive/blob/master/hive/lib/src/box/box.dart
-
您使 AuthenticationToken 可以为空,因此您的代码可以处理未来的空值。问题不在这里。问题是你没有得到未来,你得到的是空值。我不确定是什么导致了问题,但它可能与 _inMemoryToken 的类型有关。如果 _inMemoryToken 不是未来,编译器可能会感到困惑。
-
@EmreSURK 感谢您的建议。为了测试,我让 activeToken() 返回一个常量非空值或 Future,但它们仍然会出现错误:(抱歉,注释格式难以阅读):1)Future
activeToken() => Future (() => const AuthenticationToken()); 2) Future activeToken() async => const AuthenticationToken(); 3) 未来 activeToken() => _activeToken(); Future _activeToken() async => _inMemoryToken ?? (等待_tokenBox).get(_currentTokenKey); -
怎么样:Future
?
标签: flutter dart exception null mocking