Home > database >  Flutter unit test - How to test that an access to a field throws a LateInitializationError
Flutter unit test - How to test that an access to a field throws a LateInitializationError

Time:04-17

I want to test a class where a late field is not yet initialized.

Here is the code of my test :

test('Set lang method', ()  {
      // Throws an exception because the field osLang is not supposed to be initialized yet.
      expect(() => dbRepository.osLang, throwsException); 
      dbRepository.setOsLang('fr');
      expect(dbRepository.osLang, 'fr');
    });

Unfortunately, I get this error when I run my test:

package:test_api                                           expect
package:flutter_test/src/widget_tester.dart 455:16         expect
test/src/models/repositories/db_repository_test.dart 20:7  main.<fn>.<fn>

Expected: throws <Instance of 'Exception'>
  Actual: <Closure: () => String>
   Which: threw LateError:<LateInitializationError: Field '_osLang@19447861' has not been initialized.>
          stack package:my_app/src/models/repositories/db_repository.dart        DBRepository._osLang
                package:my_app/src/models/repositories/db_repository.dart 18:24  DBRepository.osLang
                test/src/models/repositories/db_repository_test.dart 20:33       main.<fn>.<fn>.<fn>
                package:test_api                                                 expect
                package:flutter_test/src/widget_tester.dart 455:16               expect
                test/src/models/repositories/db_repository_test.dart 20:7        main.<fn>.<fn>
                
          which is not an instance of 'Exception'

I tried to change the throwsException with throwsA(isA<LateInitializationError>) but my IDE doesn't find any class called LateInitializationError.

I can't find a solution to that problem on the flutter documentation, so I'm asking it here. Thanks for your answers.

CodePudding user response:

Errors aren't Exceptions, so throwsException won't match it.

LateInitializationError used to be a public type, but it seems that it isn't public anymore. You could resort to throwsA(isA<Error>()). (Based on the last available public documentation for it, it derives directly from Error, so there isn't a more specific type to test against.) You could check the Error string to be more specific:

expect(
  () => dbRepository.osLang,
  throwsA(
    predicate<Error>(
      (error) => error.toString().contains('LateInitializationError'),
    ),
  ),
);

All that said, in my opinion, testing for LateInitializationError might be a bit questionable anyway. Ideally late variables shouldn't be exposed as part of your API. If your code requires an explicit initialization step, then it'd be clearer to have an explicit check with a descriptive error message. That is, instead of:

late final String someProperty;

you could have something like:

String? _someProperty;

String get someProperty {
  var _someProperty = this._someProperty;
  if (_someProperty == null) {
    throw StateError('init() must be called first');
  }
  return _someProperty;
}

CodePudding user response:

why dont use null expression and check if its null better than late

  • Related