Unit Testing GetxController


I’m a beginner with tdd so please forgive me if it’s a dumb question.

I’m having difficulty unit testing GetxControllers. Does anyone know a simple way of doing this?
Whenever I do I get errors since Get is calling onStart and it doesn’t like the result Mockito’s giving it. I’ve tried using Mockito 5.0.1’s auto generated code as well as the older syntax, class MockController extends Mock implements Controller{}, as well as extends Fake.

The auto generated code has build errors, since Mockito is trying to use _InternalFinalCallback, but it’s not being imported as it’s private. I tried just copy pasting that part of the code into my generated file (and switching off pub build watch) but first that’s a short term solution with it’s own issues, 2nd it still doesn’t work since the onStart and onDelete functions now tell me they’re not valid overrides.

Also, I can see the get_test package but it’s documentation is basically 0, and in the examples the controller is just used directly — there’s never a mocked controller.

I tried setting Get.testMode = true; but again that doesn’t seem to do anything. And while I found that property in the docs, I didn’t find how to use it correctly.

Any help would be appreciated,

Here’s my code but the issue seems to be with the GetxControllers, so I don’t think it’s relevant much:

class FakeAuthController extends Fake implements AuthController {}

void main() {
  late MockAuthController mockAuthController;
  late FakeAuthController fakeAuthController;
  late SessionController sessionController;

  setUp(() {
    Get.testMode = true;
    mockAuthController = MockAuthController();
    fakeAuthController = FakeAuthController();

    sessionController = SessionController();

  tearDown(() {

  group('getSessionInfo', () {
    test('Calls authFacade getSignedInUserId', () async {
      await sessionController.getSessionInfo();



There really isn’t anything in my AuthController and session controller, but code is as follows:

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);

And the auto-generated, buggy mock 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() {

  int get notifierVersion =>
      (super.noSuchMethod(Invocation.getter(#notifierVersion), returnValue: 0)
          as int);
  int get notifierMicrotask =>
      (super.noSuchMethod(Invocation.getter(#notifierMicrotask), returnValue: 0)
          as int);
  bool get hasListeners =>
      (super.noSuchMethod(Invocation.getter(#hasListeners), returnValue: false)
          as bool);
  int get listeners =>
      (super.noSuchMethod(Invocation.getter(#listeners), returnValue: 0)
          as int);
  _i2._InternalFinalCallback<void> get onStart =>
              returnValue: _Fake_InternalFinalCallback<void>())
          as _i2._InternalFinalCallback<void>);
  _i2._InternalFinalCallback<void> get onDelete =>
              returnValue: _Fake_InternalFinalCallback<void>())
          as _i2._InternalFinalCallback<void>);
  bool get initialized =>
      (super.noSuchMethod(Invocation.getter(#initialized), returnValue: false)
          as bool);
  bool get isClosed =>
      (super.noSuchMethod(Invocation.getter(#isClosed), returnValue: false)
          as bool);
  String getSignedInUserId() =>
      (super.noSuchMethod(Invocation.method(#getSignedInUserId, []),
          returnValue: '') as String);
  void update([List<Object>? ids, bool? condition = true]) =>
      super.noSuchMethod(Invocation.method(#update, [ids, condition]),
          returnValueForMissingStub: null);
  void refreshGroup(Object? id) =>
      super.noSuchMethod(Invocation.method(#refreshGroup, [id]),
          returnValueForMissingStub: null);
  void removeListener(_i4.VoidCallback? listener) =>
      super.noSuchMethod(Invocation.method(#removeListener, [listener]),
          returnValueForMissingStub: null);
  void removeListenerId(Object? id, _i4.VoidCallback? listener) =>
      super.noSuchMethod(Invocation.method(#removeListenerId, [id, listener]),
          returnValueForMissingStub: null);
  _i5.Disposer addListener(_i5.GetStateUpdate? listener) =>
      (super.noSuchMethod(Invocation.method(#addListener, [listener]),
          returnValue: () {}) as _i5.Disposer);
  _i5.Disposer addListenerId(Object? key, _i5.GetStateUpdate? listener) =>
      (super.noSuchMethod(Invocation.method(#addListenerId, [key, listener]),
          returnValue: () {}) as _i5.Disposer);
  void disposeId(Object? id) =>
      super.noSuchMethod(Invocation.method(#disposeId, [id]),
          returnValueForMissingStub: null);


This question has now been answered in the GetX docs.

Pasted from the docs:


You can test your controllers like any other class, including their lifecycles:

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

  void onClose() {
    name.value = '';

  final name = 'name1'.obs;

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

void main() {
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
    expect(controller.name.value, 'name3');

    /// onClose was called

    expect(controller.name.value, '');

Mockito or mocktail

If you need to mock your GetxController/GetxService, you should extend GetxController, and mixin it with Mock, that way

class NotificationServiceMock extends GetxService with Mock implements NotificationService {}

Not exactly intuitive, is it?

Answered By – Ovidius Mazuru

Answer Checked By – Candace Johnson (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *