Search code examples
flutterdartflutter-hive

How to test Hive delete function on Flutter?


I have this test with the HiveDB that should call the 'delete' method in the function, but it doesn't pass, it goes straight to the 'put' of the "onFavoritePress" function, what I'm doing wrong?

Test:

void main() {
  late int index;
  late MockBox box;
  late HandleFavoriteImpl sut;

  setUp(() {
    index = faker.randomGenerator.integer(10);
    box = MockBox();
    box.put(index, index);
    sut = HandleFavoriteImpl(box);
  });

  test('Should call delete when the value already exists', () async {
    sut.onFavoritePress(index);

    verify(box.delete(index)).called(1);
  });
}

SUT:

class HandleFavoriteImpl {
  final Box favoritesBox;

  HandleFavoriteImpl(this.favoritesBox);

  void onFavoritePress(int index) {
    if (favoritesBox.containsKey(index)) {
      favoritesBox.delete(index);
      return;
    }
    favoritesBox.put(index, index);
  }
}

Error:

No matching calls. All calls: MockBox<dynamic>.put(2, 2), MockBox<dynamic>.containsKey(2), MockBox<dynamic>.put(2, 2)
(If you called `verify(...).called(0);`, please instead use `verifyNever(...);`.)

Solution

  • I will explain to you why the test doesn't pass and give you a way to check if an item is deleted from the Hive box.

    The Hive library methods such as delete(), put(), deleteAt()..., are asynchronous ( Future<void> ), so calling them even if it looks fast, takes some moments to resolve, so trying this code :

    // ...
    if (favoritesBox.containsKey(index)) {
      favoritesBox.delete(index);
      return;
    }
    

    Will not await until the delete() method gets resolved, so it will be executed and immediately it will return from the function, leaving the mark that the element is not deleted ( yet ) from your Hive box, you will need only to wait for it until it ends with await then return from the function, so trying this code will do it:

       Future<void> onFavoritePress(int index) async {
        if (favoritesBox.containsKey(index)) {
          await favoritesBox.delete(index);
          return;
        }
        favoritesBox.put(index, index);
      }
    

    Now, for the second thing, about knowing if an object is deleted or not from the Hive box, you will need to wrap your element(s) in a custom class, which needs to extend the HiveObject:

    @HiveType()
    class Example extends HiveObject {
      @HiveField(0)
      int index;
    }
    

    Then generating an adapter for it, please refer to this,

    Then register that adapter using:

    Hive.registerAdapter(GeneratedAdapter());
    

    Then, you will need to open a box with the type of that class:

    await Hive.openBox<Example>();
    

    Then you will have access to the isInBox property which checks for the element that exists in the assigned it's Hive box, as an example for verifying that an element is deleted:

    final example = Example();
    example.index = 10;
    
    await yourBox.put(example);
    example.isInBox; // true
    
    await yourBox.delete(example);
    example.isInBox; // false
    

    just consider that those methods are Future<void>, forgetting an await will lead to an immediate execution of the checks .