Closed mrgnhnt96 closed 2 years ago
Hi @mrgnhnt96 👋 Thanks for opening an issue!
I believe the problem is you are verifying run(any()).called(3)
first which verifies the calls successfully so they are no longer considered in future verifications.
The following passes locally
import 'package:mocktail/mocktail.dart';
import 'package:test/test.dart';
class Example {
const Example();
void run(void Function() callback) {
callback();
}
}
class Methods {
const Methods();
void foo() {}
void bar() {}
void baz() {}
}
class MockMethods extends Mock implements Methods {}
class MockExample extends Mock implements Example {}
void runner({
required Example example,
required Methods methods,
}) {
example
..run(methods.foo)
..run(methods.bar)
..run(methods.baz);
}
void main() {
late Example mockExample;
late Methods mockMethods, methods;
setUp(() {
mockExample = MockExample();
mockMethods = MockMethods();
methods = const Methods();
});
test('gracefully runs mocked callback provided to mock #run', () async {
runner(example: mockExample, methods: mockMethods);
verify(() => mockExample.run(mockMethods.foo)).called(1);
verify(() => mockExample.run(mockMethods.bar)).called(1);
verify(() => mockExample.run(mockMethods.baz)).called(1);
});
test('gracefully runs real callback provided to mock #run', () async {
runner(example: mockExample, methods: methods);
verify(() => mockExample.run(methods.foo)).called(1);
verify(() => mockExample.run(methods.bar)).called(1);
verify(() => mockExample.run(methods.baz)).called(1);
});
}
Interesting, I didn't know that they were taken from the running after they were verified. Maybe I overlooked it, thanks for letting me know!
I know extensions can't really be verified. But what if I want to verify what happens in the extension method?
In my case I am using mason_logger
, I have created an extension method called "cooking" which calls info('cooking...')
, (in an effort to stay DRY). I don't necessarily care that cooking
is called, but I do care that info('cooking...')
is called. I think that the tests still fail though
import 'package:mocktail/mocktail.dart';
import 'package:test/test.dart';
class Example {
const Example();
void run(void Function() callback) {
callback();
}
}
class Methods {
const Methods();
void foo() {}
void bar() {}
}
extension on Methods {
void baz() {
foo();
bar();
}
}
class MockMethods extends Mock implements Methods {}
class MockExample extends Mock implements Example {}
void runner({
required Example example,
required Methods methods,
}) {
example
..run(methods.foo)
..run(methods.bar)
..run(methods.baz);
}
void main() {
late Example mockExample;
late Methods mockMethods, methods;
setUp(() {
mockExample = MockExample();
mockMethods = MockMethods();
methods = const Methods();
});
test('gracefully runs mocked callback provided to mock #run', () async {
runner(example: mockExample, methods: mockMethods);
verify(() => mockExample.run(mockMethods.foo)).called(2); // Expected: <2> Actual: <1>
verify(() => mockExample.run(mockMethods.bar)).called(2); // Expected: <2> Actual: <1>
});
test('gracefully runs real callback provided to mock #run', () async {
runner(example: mockExample, methods: methods);
verify(() => mockExample.run(methods.foo)).called(2); // Expected: <2> Actual: <1>
verify(() => mockExample.run(methods.bar)).called(2); // Expected: <2> Actual: <1>
});
}
@mrgnhnt96 not sure why you expect those methods to be called twice when runner is only called once. If you want them to be called twice you'd need to call runner twice like:
import 'package:test/test.dart';
import 'package:mocktail/mocktail.dart';
class Example {
const Example();
void run(void Function() callback) {
callback();
}
}
class Methods {
const Methods();
void foo() {}
void bar() {}
}
extension on Methods {
void baz() {
foo();
bar();
}
}
class MockMethods extends Mock implements Methods {}
class MockExample extends Mock implements Example {}
void runner({
required Example example,
required Methods methods,
}) {
example
..run(methods.foo)
..run(methods.bar)
..run(methods.baz);
}
void main() {
late Example mockExample;
late Methods mockMethods, methods;
setUp(() {
mockExample = MockExample();
mockMethods = MockMethods();
methods = const Methods();
});
test('gracefully runs mocked callback provided to mock #run', () async {
runner(example: mockExample, methods: mockMethods);
runner(example: mockExample, methods: mockMethods);
verify(() => mockExample.run(mockMethods.foo)).called(2);
verify(() => mockExample.run(mockMethods.bar)).called(2);
});
test('gracefully runs real callback provided to mock #run', () async {
runner(example: mockExample, methods: methods);
runner(example: mockExample, methods: methods);
verify(() => mockExample.run(methods.foo)).called(2);
verify(() => mockExample.run(methods.bar)).called(2);
});
}
Let me know if that helps or if I missed something. Closing for now but I'm happy to continue the conversation 👍
Describe the bug When passing a
void Function()
as an arg,verify()
seems to always fail.Code to Reproduce
Logs
gracefully runs mocked callback provided to mock #run
```console No matching calls. All calls: [VERIFIED] MockExample.run(Closure: () => void from Function 'foo':.), [VERIFIED] MockExample.run(Closure: () => void from Function 'bar':.), [VERIFIED] MockExample.run(Closure: () => void) (If you called `verify(...).called(0);`, please instead use `verifyNever(...);`.) package:test_api fail package:mocktail/src/mocktail.dart 723:7 _VerifyCall._checkWith package:mocktail/src/mocktail.dart 516:18 _makeVerify.gracefully runs real callback provided to mock #run
```console No matching calls. All calls: [VERIFIED] MockExample.run(Closure: () => void from Function 'foo':.), [VERIFIED] MockExample.run(Closure: () => void from Function 'bar':.), [VERIFIED] MockExample.run(Closure: () => void) (If you called `verify(...).called(0);`, please instead use `verifyNever(...);`.) package:test_api fail package:mocktail/src/mocktail.dart 723:7 _VerifyCall._checkWith package:mocktail/src/mocktail.dart 516:18 _makeVerify.flutter doctor
```console [✓] Flutter (Channel stable, 2.10.1, on macOS 12.1 21C52 darwin-arm, locale en-US) • Flutter version 2.10.1 at /Users/morganhunt/Development/versions/stable • Upstream repository https://github.com/flutter/flutter.git • Framework revision db747aa133 (13 days ago), 2022-02-09 13:57:35 -0600 • Engine revision ab46186b24 • Dart version 2.16.1 • DevTools version 2.9.2 [!] Android toolchain - develop for Android devices (Android SDK version 29.0.3) • Android SDK at /Users/morganhunt/Library/Android/sdk ✗ cmdline-tools component is missing Run `path/to/sdkmanager --install "cmdline-tools;latest"` See https://developer.android.com/studio/command-line for more details. ✗ Android license status unknown. Run `flutter doctor --android-licenses` to accept the SDK licenses. See https://flutter.dev/docs/get-started/install/macos#android-setup for more details. [✓] Xcode - develop for iOS and macOS (Xcode 13.2.1) • Xcode at /Applications/Xcode.app/Contents/Developer • CocoaPods version 1.11.2 [✓] Chrome - develop for the web • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome [✓] Android Studio (version 4.1) • Android Studio at /Applications/Android Studio.app/Contents • Flutter plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/9212-flutter • Dart plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/6351-dart • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6915495) [✓] VS Code (version 1.64.2) • VS Code at /Applications/Visual Studio Code.app/Contents • Flutter extension version 3.34.0 [✓] Connected device (1 available) • Chrome (web) • chrome • web-javascript • Google Chrome 98.0.4758.102 ! Error: iPhone is not connected. Xcode will continue when iPhone is connected. (code -13) [✓] HTTP Host Availability • All required HTTP hosts are available ! Doctor found issues in 1 category. ```