shuster
shuster

Reputation: 452

How to test a void function in Dart?

I am new to unit tests in Dart/Flutter and I would like to write a test for a void function. When functions return something I am writing a test like this:

test('Gets user save', () async {
      final userSave = await mockSource!.getUserSave();
      expect(userSave!.age, equals(20));
});

In such a scenario like above expect can be used since getUserSave function returns a user model.

How about checking if test passes of fails for a void/Future function like below? I can not use expect because it does not return a value.

Future<void> clearUserSave() async {
    DatabaseClient mockDBClient = MockDatabaseClientImpl();
    mockDBClient.clear();
}

I use flutter_test and mockito for testing.

Upvotes: 1

Views: 8391

Answers (6)

alexey.popkov
alexey.popkov

Reputation: 96

It seems, if result type is void, you can only verify expected calls.

import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';

import 'test_usecase_test.mocks.dart';

@GenerateNiceMocks([MockSpec<TestRepo>()])
class TestRepo {
  void doSomethingSync(String parameters) {}

  Future<void> doSomething(String parameters) async {}
}

class TestUsecase {
  final TestRepo repo;

  const TestUsecase({required this.repo});

  Future<void> execute(String parameters) async {
    repo.doSomethingSync(parameters);
    await repo.doSomething(parameters);
  }
}

void main() {
  test('test', () async {
    final repo = MockTestRepo();
    final usecase = TestUsecase(repo: repo);

    when(
      repo.doSomethingSync('parameters'),
    ).thenReturn(null);

    when(
      repo.doSomething('parameters'),
    ).thenAnswer(
      (_) => Future.value(),
    );

    await usecase.execute('parameters');

    verifyInOrder(
      [
        repo.doSomethingSync('parameters'),
        repo.doSomething('parameters'),
      ],
    );
  });
}

Upvotes: 0

Srinadh
Srinadh

Reputation: 566

Just an addition to above answers. If you are using mokito package. you can use thenAnswer.

        when(mockClass
            .voidReturningFunctionWithSomePeramerters(argThat(isNotNull)))
        .thenAnswer((_) {}); // <-- returns void.

Upvotes: 1

iamdipanshus
iamdipanshus

Reputation: 600

You can expect the result to be a Future<void>, like:

expect(
  mockSource!. clearUserSave(),
  isA<Future<void>>(),
);

Upvotes: 0

Abhishek Ghimire
Abhishek Ghimire

Reputation: 2426

testing a function that return void :

  expect(
      () async => await functionThatReturnsVoid(),
      isA<void>(),
    );

Upvotes: 5

abdelrahman abied
abdelrahman abied

Reputation: 297

you can add nullable variable and assign variable value in method, after call method check if this varaible isNotNull like this:

test('Gets user save', () async {
  await mockSource?.getUserSave();
  final userSave=mockSource.user;
  expect(userSave,isNotNull );

});

Upvotes: 1

mmcdon20
mmcdon20

Reputation: 6701

Typically a void function will produce a side effect of some sort. When writing a test for a void function, I would check whatever state is effected by the void function before and after calling the function to be sure that the desired side effect has occurred.

In this specific case, you are calling clear on a DatabaseClient. I don't know the specifics of the DatabaseClient api, but I would construct a test where the client contains some data before calling clear, and then check that the data is no longer there after calling clear.

Something along the lines of this:

Future<void> clearUserSave() async {
    DatabaseClient mockDBClient = MockDatabaseClientImpl();
    mockDBClient.add(SOMEDATA);
    expect(mockDBClient.hasData, true);
    mockDBClient.clear();
    expect(mockDBClient.hasData, false);
}

Upvotes: 4

Related Questions