我是一名tdd初学者,如果问题很蠢,请原谅。
我在对GetxControllers进行单元测试时遇到了困难。有没有人知道一个简单的方法来做到这一点?每次尝试时都会出现错误,因为Get正在调用onStart,并且它不喜欢Mockito给它的结果。我尝试使用Mockito 5.0.1的自动生成代码以及旧语法、类MockController扩展Mock实现Controller{},以及扩展Fake。
自动生成的代码有构建错误,因为Mockito试图使用_InternalFinalCallback,但它没有被导入,因为它是私有的。我尝试将代码的那部分复制粘贴到我的生成文件中(并关闭pub build watch),但首先这是一个短期解决方案,它有自己的问题,其次,现在onStart和onDelete函数告诉我它们不是有效的覆盖。
此外,我可以看到get_test包,但其中的文档基本上是0,在示例中控制器仅直接使用--从未使用模拟控制器。
我尝试设置Get.testMode = true; 但同样似乎没有任何作用。虽然我在文档中找到了该属性,但我没有找到如何正确使用它。
非常感谢任何帮助,但问题似乎与GetxControllers相关,所以我认为我的代码不是很重要:
class FakeAuthController extends Fake implements AuthController {}
@GenerateMocks([AuthController])
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
late MockAuthController mockAuthController;
late FakeAuthController fakeAuthController;
late SessionController sessionController;
setUp(() {
Get.testMode = true;
mockAuthController = MockAuthController();
fakeAuthController = FakeAuthController();
Get.put<AuthController>(mockAuthController);
sessionController = SessionController();
});
tearDown(() {
Get.delete<AuthController>();
});
group('getSessionInfo', () {
test('Calls authFacade getSignedInUserId', () async {
await sessionController.getSessionInfo();
when(Get.find<AuthController>()).thenReturn(fakeAuthController);
verify(mockAuthController.getSignedInUserId());
});
});
}
我的 AuthController 和 session controller 中实际上没有任何代码,但是它们的代码如下所示:
import 'package:get/get.dart';
class AuthController extends GetxController {
String getSignedInUserId() {
// await Future.delayed(Duration(milliseconds: 1));
return '1';
}
}
import 'package:get/get.dart';
import '../../auth/controllers/auth_controller.dart';
import '../models/session_info.dart';
class SessionController extends GetxController {
final AuthController authController = Get.find<AuthController>();
Rx<SessionInfo> sessionInfo = Rx<SessionInfo>();
Future<void> getSessionInfo() async {
// authController.getSignedInUserId();
// sessionInfo.value = SessionInfo(userId: userId);
}
}
和自动生成的有缺陷的模拟控制器:
// Mocks generated by Mockito 5.0.1 from annotations
// in smart_locker_controller/test/shared/controllers/session_controller_test.dart.
// Do not manually edit this file.
import 'dart:ui' as _i4;
import 'package:get/get_instance/src/lifecycle.dart' as _i2;
import 'package:get/get_state_manager/src/simple/list_notifier.dart' as _i5;
import 'package:mockito/mockito.dart' as _i1;
import 'package:smart_locker_controller/auth/controllers/auth_controller.dart'
as _i3;
// ignore_for_file: comment_references
// ignore_for_file: unnecessary_parenthesis
class _Fake_InternalFinalCallback<T> extends _i1.Fake
implements _i2._InternalFinalCallback<T> {}
/// A class which mocks [AuthController].
///
/// See the documentation for Mockito's code generation for more information.
class MockAuthController extends _i1.Mock implements _i3.AuthController {
MockAuthController() {
_i1.throwOnMissingStub(this);
}
@override
int get notifierVersion =>
(super.noSuchMethod(Invocation.getter(#notifierVersion), returnValue: 0)
as int);
@override
int get notifierMicrotask =>
(super.noSuchMethod(Invocation.getter(#notifierMicrotask), returnValue: 0)
as int);
@override
bool get hasListeners =>
(super.noSuchMethod(Invocation.getter(#hasListeners), returnValue: false)
as bool);
@override
int get listeners =>
(super.noSuchMethod(Invocation.getter(#listeners), returnValue: 0)
as int);
@override
_i2._InternalFinalCallback<void> get onStart =>
(super.noSuchMethod(Invocation.getter(#onStart),
returnValue: _Fake_InternalFinalCallback<void>())
as _i2._InternalFinalCallback<void>);
@override
_i2._InternalFinalCallback<void> get onDelete =>
(super.noSuchMethod(Invocation.getter(#onDelete),
returnValue: _Fake_InternalFinalCallback<void>())
as _i2._InternalFinalCallback<void>);
@override
bool get initialized =>
(super.noSuchMethod(Invocation.getter(#initialized), returnValue: false)
as bool);
@override
bool get isClosed =>
(super.noSuchMethod(Invocation.getter(#isClosed), returnValue: false)
as bool);
@override
String getSignedInUserId() =>
(super.noSuchMethod(Invocation.method(#getSignedInUserId, []),
returnValue: '') as String);
@override
void update([List<Object>? ids, bool? condition = true]) =>
super.noSuchMethod(Invocation.method(#update, [ids, condition]),
returnValueForMissingStub: null);
@override
void refreshGroup(Object? id) =>
super.noSuchMethod(Invocation.method(#refreshGroup, [id]),
returnValueForMissingStub: null);
@override
void removeListener(_i4.VoidCallback? listener) =>
super.noSuchMethod(Invocation.method(#removeListener, [listener]),
returnValueForMissingStub: null);
@override
void removeListenerId(Object? id, _i4.VoidCallback? listener) =>
super.noSuchMethod(Invocation.method(#removeListenerId, [id, listener]),
returnValueForMissingStub: null);
@override
_i5.Disposer addListener(_i5.GetStateUpdate? listener) =>
(super.noSuchMethod(Invocation.method(#addListener, [listener]),
returnValue: () {}) as _i5.Disposer);
@override
_i5.Disposer addListenerId(Object? key, _i5.GetStateUpdate? listener) =>
(super.noSuchMethod(Invocation.method(#addListenerId, [key, listener]),
returnValue: () {}) as _i5.Disposer);
@override
void disposeId(Object? id) =>
super.noSuchMethod(Invocation.method(#disposeId, [id]),
returnValueForMissingStub: null);
}