Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't use any() to verify StackTrace #174

Closed
tijanirf opened this issue Jan 1, 2023 · 2 comments
Closed

Can't use any() to verify StackTrace #174

tijanirf opened this issue Jan 1, 2023 · 2 comments
Assignees
Labels
question Further information is requested waiting for response Waiting for follow up

Comments

@tijanirf
Copy link

tijanirf commented Jan 1, 2023

Bug Description
In this method, I want to catch the exception and the stack trace. I got into trouble when I want to verify the broadcastPort.notifyCoreEvent(). This is the method I want to test:

real_method.dart:

@override
Future<CategoryDto> addCategory(CategoryDto category) async {
  try {
    Category(category).validate(insert: true);
    final result = await persistencePort.createCategory(category);

    broadcastPort?.notifyCoreEvent(
      CoreEvent.categoryCreatedEvent,
      request: category,
      response: result,
    );

    return result;
  } catch (e, s) {
    broadcastPort?.notifyCoreEvent(
      CoreEvent.exceptionThrownEvent,
      exception: e,
      stackTrace: s,
    );

    rethrow;
  }
}

This is how I tested it:

real_method_test.dart:

class FakeCoreDomainException extends Fake implements CoreDomainException {}
class FakeStackTrace extends Fake implements StackTrace {}

// Test's main starts here...

setUpAll(() {
  registerFallbackValue(CoreEvent.exceptionThrownEvent);
  registerFallbackValue(FakeCoreDomainException());
  registerFallbackValue(FakeStackTrace());
});

// Some statements here...

test('Insert invalid category and broadcast port is not omitted, insertion failed', () async {
  final exception =
      CoreDomainException(CoreDomainExceptionType.invalidCategoryTitle);

  when(() => mockPersistencePort.createCategory(dummyCategoryDto))
      .thenThrow(exception);

  expect(
    () => coreService.addCategory(dummyCategoryDto),
    throwsA(
      exception,
    ),
  );

  verify(() => mockPersistencePort.createCategory(dummyCategoryDto))
      .called(1);

  verify(
    () => mockBroadcastPort.notifyCoreEvent(
      CoreEvent.exceptionThrownEvent,
      exception: exception,
      stackTrace: any(),
    ),
  ).called(1);
});

But I got this error:

Invalid argument(s): An argument matcher (like `any()`) was either not used as an immediate argument to Symbol("notifyCoreEvent") (argument matchers can only be used as an argument for the very method being stubbed or verified), or was used as a named argument without the Mocktail "named" API (Each argument matcher that is used as a named argument needs to specify the name of the argument it is being used in. For example: `when(() => obj.fn(x: any(named: "x")))`).

I tried to change stackTrace: any() tostackTrace: any(that: isA<StackTrace>()), but still got this error.

By the way, If I omit the stack trace on the real method call, the test will be passed.

modified_real_method.dart:

@override
Future<CategoryDto> addCategory(CategoryDto category) async {
  try {

  // Some statements here...

  } catch (e) {
    broadcastPort?.notifyCoreEvent(
      CoreEvent.exceptionThrownEvent,
      exception: e,
    );

    rethrow;
  }
}

modified_real_method_test.dart:

setUpAll(() {
  registerFallbackValue(CoreEvent.exceptionThrownEvent);
});

// Some statements here...

test('Insert invalid category and broadcast port is not omitted, insertion failed', () async {
  final exception =
      CoreDomainException(CoreDomainExceptionType.invalidCategoryTitle);

  when(() => mockPersistencePort.createCategory(dummyCategoryDto))
      .thenThrow(exception);

  expect(
    () => coreService.addCategory(dummyCategoryDto),
    throwsA(
      exception,
    ),
  );

  verify(() => mockPersistencePort.createCategory(dummyCategoryDto))
      .called(1);

  verify(
    () => mockBroadcastPort.notifyCoreEvent(
      CoreEvent.exceptionThrownEvent,
      exception: exception,
    ),
  ).called(1);
});

Expected behavior
stackTrace: any() should be enough to make real_method_test.dart passed. Because I have another similar use case for verifying mockNavigatorObserver.didPush() and it is working.

class FakeRoute extends Fake implements Route {}

// Test's main starts here...

testWidget('Some navigation test', () {
  setUpAll(() {
    registerFallbackValue(FakeRoute());
  }

  // Some statements here...

  await tester.pumpWidget(
    MultiRepositoryProvider(
      providers: [
        RepositoryProvider<BaseLocationService>.value(
          value: mockLocationService,
        ),
      ],
      child: MultiBlocProvider(
        providers: [
          BlocProvider<LocationCubit>(
            create: (_) => mockLocationCubit,
          ),
        ],
        child: MaterialApp(
          onGenerateRoute: _appRouter.onGenerateRoute,
          navigatorObservers: [mockNavigatorObserver],
          home: const ActivateLocationScreen(),
        ),
      ),
    ),
  );

  // Some statements here...

  verify(() => mockNavigatorObserver.didPush(any(), any()));
});

Environment
Dart: 2.18.4 (My project is a dart package)
Mocktail: 0.3.0

Additional context
I am thinking that maybe we can provide an optional StackTrace parameter on the thenThrow()

@thide11
Copy link

thide11 commented Jan 20, 2023

Change
stackTrace: any(),
to
stackTrace: any(named: "stackTrace")
All named parameters with any() need to have this

@felangel felangel added question Further information is requested waiting for response Waiting for follow up labels Jan 20, 2023
@tijanirf
Copy link
Author

tijanirf commented Jan 23, 2023

Change stackTrace: any(), to stackTrace: any(named: "stackTrace") All named parameters with any() need to have this

Hi @thide11, thanks for the response. Let me check it first

Update:

The solution works, thanks for the help. I'll close the issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested waiting for response Waiting for follow up
Projects
None yet
Development

No branches or pull requests

3 participants