jonataslaw / getx

Open screens/snackbars/dialogs/bottomSheets without context, manage states and inject dependencies easily with Get.
MIT License
10.34k stars 1.62k forks source link

Expect states in order in tests #2248

Open spoonsoftbl opened 2 years ago

spoonsoftbl commented 2 years ago

Is it possible to see all state changes in test ? Here example:

class ExampleController extends GetxController {

    final RxInt testInt = 0.obs;

    void exampleVoid() {
        testInt.value = 1;
        testInt.value = 2;
        testInt.value = 3;
        testInt.value = 4;
        testInt.value = 5;
    }

} 
test('''Example test''', () {
      expect(controller.testInt, 0);
      controller.exampleVoid();
      expect(controller.testInt, 1);
      expect(controller.testInt, 2);
      expect(controller.testInt, 3);
      expect(controller.testInt, 4);
      expect(controller.testInt, 5);
  });

Now we can check only last value in expect (here 5).

jonataslaw commented 2 years ago

I don't think so, if the state change happened in the same void, only the last one will be observed from the build, so it doesn't make sense to test the state of something that doesn't exist. Unless you make the operation asynchronous and await a pump to wait for the build to occur, after each state change.

spoonsoftbl commented 2 years ago

Here is a more real case where I need to set flag loadingViewVisible and test every possible scenario in unit test (with emailValidation error or error from usecase/backend). Show error event - show error snackbar on view class.

import 'package:email_validator/email_validator.dart';
import 'package:event/event.dart';
import 'package:get/get.dart';
import 'package:shared/common/utils/strings.dart';

import 'forget_password_event_args.dart';
import 'forget_password_use_case.dart';

class ForgetPasswordController extends GetxController {
  final Event<ForgetPasswordEventArgs> forgetPasswordEvent;
  final ForgetPasswordUseCase forgetPasswordUseCase;

  ForgetPasswordController(
      {required this.forgetPasswordEvent, required this.forgetPasswordUseCase});

  final RxBool loadingViewVisible = false.obs;

  Future<void> forgetPassword(String email) async {
    loadingViewVisible.value = true;
    if (_isValidEmail(email)) {
      try {
        await forgetPasswordUseCase.forgetPassword(email);
        forgetPasswordEvent.broadcast(ForgetPasswordEventArgs.showDialog());
      } catch (err) {
        forgetPasswordEvent
            .broadcast(ForgetPasswordEventArgs.showError(err.toString()));
        rethrow;
      } finally {
        loadingViewVisible.value = false;
      }
    } else {
      loadingViewVisible.value = false;
      forgetPasswordEvent
          .broadcast(ForgetPasswordEventArgs.showError(Strings.emailNotValid));
    }
  }

  //region Private methods
  bool _isValidEmail(String email) => EmailValidator.validate(email);
  //endregion
}
spoonsoftbl commented 2 years ago

In RxJava we have assertValues method: https://www.tabnine.com/code/java/methods/io.reactivex.observers.TestObserver/assertValues