gpt4 book ai didi

flutter - 单元测试 GetxController

转载 作者:行者123 更新时间:2023-12-03 17:43:37 34 4
gpt4 key购买 nike

我是 tdd 的初学者,所以如果这是一个愚蠢的问题,请原谅我。
我在对 GetxControllers 进行单元测试时遇到困难。有谁知道这样做的简单方法?
每当我这样做时,我都会收到错误,因为 Get 正在调用 onStart 并且它不喜欢 Mockito 给出的结果。我尝试过使用 Mockito 5.0.1 的自动生成代码以及旧语法,MockController 类扩展 Mock 实现 Controller{},以及扩展 Fake。
自动生成的代码有构建错误,因为 Mockito 正在尝试使用 _InternalFinalCallback,但它没有被导入,因为它是私有(private)的。我尝试将那部分代码复制粘贴到我生成的文件中(并关闭 pub build watch)但首先这是一个短期解决方案,它有自己的问题,第二它仍然不起作用,因为 onStart 和 onDelete 函数现在告诉我它们不是有效的覆盖。
另外,我可以看到 get_test 包,但它的文档基本上是 0,并且在示例中, Controller 只是直接使用 - 从来没有模拟 Controller 。
我尝试设置 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);
}
}

以及自动生成的、有缺陷的模拟 Controller :
// 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);
}

最佳答案

这个问题现已在 GetX 文档中得到解答。
从文档粘贴:
测试
您可以像任何其他类一样测试您的 Controller ,包括它们的生命周期:

class Controller extends GetxController {
@override
void onInit() {
super.onInit();
//Change value to name2
name.value = 'name2';
}

@override
void onClose() {
name.value = '';
super.onClose();
}

final name = 'name1'.obs;

void changeName() => name.value = 'name3';
}

void main() {
test('''
Test the state of the reactive variable "name" across all of its lifecycles''',
() {
/// You can test the controller without the lifecycle,
/// but it's not recommended unless you're not using
/// GetX dependency injection
final controller = Controller();
expect(controller.name.value, 'name1');

/// If you are using it, you can test everything,
/// including the state of the application after each lifecycle.
Get.put(controller); // onInit was called
expect(controller.name.value, 'name2');

/// Test your functions
controller.changeName();
expect(controller.name.value, 'name3');

/// onClose was called
Get.delete<Controller>();

expect(controller.name.value, '');
});
}
Mockito 或无酒精鸡尾酒
如果您需要模拟您的 GetxController/GetxService,您应该扩展 GetxController,并将其与 Mock 混合,这样
class NotificationServiceMock extends GetxService with Mock implements NotificationService {}
不完全直观,是吗?

关于flutter - 单元测试 GetxController,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66685369/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com