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()