dart-lang / mockito

Mockito-inspired mock library for Dart
https://pub.dev/packages/mockito
Apache License 2.0
623 stars 160 forks source link

`verify` failing test but showing in "All calls" #724

Open tristanjclarke opened 6 months ago

tristanjclarke commented 6 months ago

I'm trying to run a test to determine if a method is called. In order to do this I'm using the verify method from the mockito package.

However, I'm finding that the verify method is failing even though it shows up in the list of calls that were made during the test.

Test

  test('run() schedules activities if none currently exist', () {
    return withClock(Clock.fixed(DateTime(2023, 11, 22)), () async {
      final task = ScheduleActivitiesTask(
        userRepository: userRepository,
        relationshipRepository: relationshipRepository,
        activityRepository: activityRepository,
        lessonOverviewRepository: lessonOverviewRepository,
        questionOverviewRepository: questionOverviewRepository,
        checkInOverviewRepository: checkInOverviewRepository,
      );

      const user = User(
        id: 'user_id',
        invitationCode: 'invitation_code',
        relationshipId: null,
      );
      final relationship = Relationship(
        id: 'relationship_id',
        userIds: [user.id],
        activitiesGeneratedAt: null,
      );
      final lessonActivities = [
        Activity(
          id: null,
          type: ActivityType.lesson,
          userIds: [user.id],
          userDetails: [
            ActivityUserDetails(
              userId: user.id,
              status: ActivityStatus.notStarted,
              completedAt: null,
            ),
          ],
          overviewId: 'lesson_overview_id_1',
          plannedAt: DateTime(2023, 11, 22),
        ),
        Activity(
          id: null,
          type: ActivityType.lesson,
          userIds: [user.id],
          userDetails: [
            ActivityUserDetails(
              userId: user.id,
              status: ActivityStatus.notStarted,
              completedAt: null,
            ),
          ],
          overviewId: 'lesson_overview_id_2',
          plannedAt: DateTime(2023, 11, 23),
        ),
      ];
      final questionActivities = <Activity>[
        QuestionActivity(
          userIds: [user.id],
          userDetails: [
            ActivityUserDetails(
              userId: user.id,
              status: ActivityStatus.notStarted,
              completedAt: null,
            ),
          ],
          overviewId: 'question_overview_id_1',
          plannedAt: DateTime(2023, 11, 22),
        ),
        QuestionActivity(
          userIds: [user.id],
          userDetails: [
            ActivityUserDetails(
              userId: user.id,
              status: ActivityStatus.notStarted,
              completedAt: null,
            ),
          ],
          overviewId: 'question_overview_id_2',
          plannedAt: DateTime(2023, 11, 23),
        ),
      ];
      final checkInActivities = <Activity>[
        CheckInActivity(
          userIds: [user.id],
          userDetails: [
            ActivityUserDetails(
              userId: user.id,
              status: ActivityStatus.notStarted,
              completedAt: null,
            ),
          ],
          overviewId: 'check_in_overview_id_1',
          plannedAt: DateTime(2023, 11, 6),
        ),
        CheckInActivity(
          userIds: [user.id],
          userDetails: [
            ActivityUserDetails(
              userId: user.id,
              status: ActivityStatus.notStarted,
              completedAt: null,
            ),
          ],
          overviewId: 'check_in_overview_id_2',
          plannedAt: DateTime(2023, 11, 6),
        ),
      ];
      final lessonOverviews = [
        const LessonOverview(
          id: 'lesson_overview_id_1',
          category: LessonCategory.foundationWeek,
          order: 1,
          title: 'title',
          subtitle: 'subtitle',
          description: 'description',
          points: 1,
          duration: Duration(minutes: 1),
          steps: [],
        ),
        const LessonOverview(
          id: 'lesson_overview_id_2',
          category: LessonCategory.foundationWeek,
          order: 2,
          title: 'title',
          subtitle: 'subtitle',
          description: 'description',
          points: 1,
          duration: Duration(minutes: 1),
          steps: [],
        ),
      ];
      final questionOverviews = [
        const QuestionOverview(
          id: 'question_overview_id_1',
          tag: TagV2.communication,
          title: 'title',
          value: 'value',
          points: 1,
          duration: Duration(minutes: 1),
        ),
        const QuestionOverview(
          id: 'question_overview_id_2',
          tag: TagV2.communication,
          title: 'title',
          value: 'value',
          points: 1,
          duration: Duration(minutes: 1),
        ),
      ];
      final checkInOverviews = [
        const CheckInOverviewV2(
          id: 'check_in_overview_id_1',
          title: 'title',
          subtitle: 'subtitle',
          points: 1,
          duration: Duration(minutes: 1),
          surpriseQuestion: CheckInSurpriseQuestion(
            id: 'id',
            value: 'question',
          ),
          questions: [],
        ),
        const CheckInOverviewV2(
          id: 'check_in_overview_id_2',
          title: 'title',
          subtitle: 'subtitle',
          points: 1,
          duration: Duration(minutes: 1),
          surpriseQuestion: CheckInSurpriseQuestion(
            id: 'id',
            value: 'question',
          ),
          questions: [],
        ),
      ];

      when(activityRepository.list(userId: user.id)).thenAnswer(
        (_) => Future.value(null),
      );

      when(userRepository.get(user.id)).thenAnswer(
        (_) => Future.value(user),
      );

      when(relationshipRepository.get(
        id: user.invitationCode!,
        isTemporary: true,
      )).thenAnswer(
        (_) => Future.value(relationship),
      );

      when(
        lessonOverviewRepository.list(
          category: LessonCategory.tutorial,
        ),
      ).thenAnswer(
        (_) => Future.value([]),
      );

      when(
        lessonOverviewRepository.list(
          category: LessonCategory.foundationWeek,
        ),
      ).thenAnswer(
        (_) => Future.value(lessonOverviews),
      );

      for (final tag in TagV2.values) {
        if (tag == TagV2.communication) {
          when(questionOverviewRepository.list(tag: TagV2.communication))
              .thenAnswer(
            (_) => Future.value(questionOverviews),
          );
        } else {
          when(questionOverviewRepository.list(tag: tag)).thenAnswer(
            (_) => Future.value([]),
          );
        }
      }

      when(checkInOverviewRepository.list()).thenAnswer(
        (_) => Future.value(checkInOverviews),
      );

      await task.run(
        userId: user.id,
        partnerId: null,
        lastScheduledAt: null,
      );

      verify(
        relationshipRepository.update(
          relationship: relationship.copyWith(
            activitiesGeneratedAt: () => clock.now(),
          ),
          isTemporary: true,
        ),
      );

      verifyNever(activityRepository.deleteAll(
        activities: anyNamed('activities'),
      ));

      verify(activityRepository.insertAll(
        activities: anyNamed('activities'),
      )).called(1);

      verify(activityRepository.insertAll(
        activities: lessonActivities,
      ));
    });
  });

Result

package:matcher                                       fail
package:mockito/src/mock.dart 797:7                   _VerifyCall._checkWith
package:mockito/src/mock.dart 1071:18                 _makeVerify.<fn>
test/tasks/schedule_activities_task_test.dart 644:15  main.<fn>.<fn>.<fn>

No matching calls. All calls: MockActivityRepository.list({userId: user_id}), [VERIFIED] MockActivityRepository.insertAll({activities: [Activity(id: null, userIds: [user_id], userDetails: [ActivityUserDetails(userId: user_id, status: ActivityStatus.notStarted, completedAt: null, )], overviewId: lesson_overview_id_1, type: ActivityType.lesson, plannedAt: 2023-11-22 00:00:00.000, ), Activity(id: null, userIds: [user_id], userDetails: [ActivityUserDetails(userId: user_id, status: ActivityStatus.notStarted, completedAt: null, )], overviewId: lesson_overview_id_2, type: ActivityType.lesson, plannedAt: 2023-11-23 00:00:00.000, )]})
(If you called `verify(...).called(0);`, please instead use `verifyNever(...);`.)
srawlins commented 6 months ago

It looks like the first verify(activeRepository.insertAll call is verified. Then, the second fails, because the verified call is excluded. See the "Note, when mockito verifies" text in the docs.