skip to Main Content

I try to verify the state of another bloc is changed with bloc_test but not sure how to do.

The situation is like that

  • BlocA has an event called SignIn
  • BlocB has an item in state called User, which is updated with event called UserChanged

I would like to verify that when BlocA.add(SignIn()), the User in BlocB is updated with specific values.

My current idea is

act: (blocA) {
        blocA.add(SignIn());
      },
verify: (bloc) {
        verify(() => BlocB.add(
              UserChanged(
                user: any(
                  named: "user",
                  that: isA<User>().having(
                    (user) => user.email,
                    "email",
                    "[email protected]",
                  ),
                ),
              ),
            )).called(1);
      },

But I got the following error

Invalid argument(s): An ArgumentMatcher was declared as named user, but was not passed as an argument named user.

BAD:  when(() => obj.fn(any(named: "a")))
GOOD: when(() => obj.fn(a: any(named: "a")))

Please advice how I can achieve it. Thank you

===============================================

Update: my test will pass if I do not verify the argument passed to UserChanged event, such as

act: (blocA) {
        blocA.add(SignIn());
      },
verify: (bloc) {
        verify(() => BlocB.add(any<UserChanged>())).called(1);
      },

2

Answers


  1. I think it’s not the best idea to test the way you want.
    I would prefer to have 3 tests:

    1. Check the state of Bloc A on the SignIn event
    2. Check the state of Bloc B on the UserChanged event
    3. Mock Bloc A and Bloc B and verify that the respective state update methods of both Blocs were called
    Login or Signup to reply.
  2. yes, at least I did the same.
    You need to check the proper states and method execution separately.

    test(
      'WHEN user does smth'
      'THEN adds new states for Bloc A and Bloc B',
      () async {
        await _callUseCase();
    
        verify(blocA.setLoaded()).called(1);
        verify(blocB.setChanged()).called(1);
      },
    );
    

    So the test above is for that use case:

    class UseCase {
     const UseCase({
    required this.blocA,
    required this.blocB,
    required this.repoA,
    });
    
    final BlocA blocA;
    final BlocB blocB;
    final RepoA repoA;
    
    Future<bool> call(Payload payload) async {
      final List<Account> accounts = blocA.state.allTradingAccounts;
      try {
        blocA.setUpdating();
        final result = await repoA(payload);
        blocA.setLoaded([
          result,
          ...accounts,
        ]);
        blocB.setChanged(MyType.real);
        return true;
      } catch (error, stack) {
        blocA.setLoaded(accounts);
        return false;
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search