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

When throws exception when stubbing response #37

Closed
haashem opened this issue Mar 21, 2021 · 9 comments
Closed

When throws exception when stubbing response #37

haashem opened this issue Mar 21, 2021 · 9 comments
Assignees
Labels
question Further information is requested

Comments

@haashem
Copy link

haashem commented Mar 21, 2021

Here we have:

class Cat {
  Future<void> hunt(String place, String prey) async => prey;
}

then in test file:
[for demonstration, test doesn't do anything]

class MockCat extends Mock implements Cat {}

void main() {
late MockCat cat;
setUp(() {
    cat = MockCat();
  });

group('Cat behaviors', () {
    test('verify cat can hunt', () {
      when(() => cat.hunt('yard', 'mouse')).thenAnswer((invocation) async => 'mouse');
    });
  });
}

then it throws

_TypeError (type 'Null' is not a subtype of type 'Future<void>')

I have upgraded 'bloc_test' to 8.0.0 and while updating the tests because of syntax change, I face the above error.

What am I doing wrong?

Flutter doctor
[✓] Flutter (Channel beta, 2.0.1, on macOS 11.0.1 20B29 darwin-x64, locale en-US)
    • Flutter version 2.0.1 at /Users/hashem/Desktop/Xcode_Projects/flutter
    • Framework revision c5a4b4029c (2 weeks ago), 2021-03-04 09:47:48 -0800
    • Engine revision 40441def69
    • Dart version 2.12.0

[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.2)
    • Android SDK at /Users/hashem/Library/Android/sdk
    • Platform android-30, build-tools 30.0.2
    • Java binary at: /Applications/Android
      Studio.app/Contents/jre/jdk/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6222593)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Xcode 12.4, Build version 12D4e
    • CocoaPods version 1.10.1

[✓] 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-6222593)

[✓] VS Code (version 1.54.3)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.20.0

[✓] Connected device (3 available)
    • Hashem’s iPhone (mobile)   • 00008030-00124C3021BA802E            • ios            •
      iOS 14.4
    • iPhone 12 Pro Max (mobile) • 6E489C41-27D7-4EE7-A1A7-3383C53F1452 • ios            •
      com.apple.CoreSimulator.SimRuntime.iOS-14-4 (simulator)
    • Chrome (web)               • chrome                               • web-javascript •
      Google Chrome 89.0.4389.90

• No issues found!
@SAGARSURI
Copy link

SAGARSURI commented Mar 22, 2021

Weird! For me, the test case passed. My dart version is 2.12.2

@felangel felangel self-assigned this Mar 22, 2021
@felangel felangel added question Further information is requested waiting for response Waiting for follow up labels Mar 22, 2021
@felangel
Copy link
Owner

Hi @haashem 👋
Thanks for opening an issue!

Are you using mocktail instead of mockito? I’m guessing you are still using mockito which is why the test is failing. If you’re having trouble after switching to mocktail then can you please provide a complete reproduction sample? Thanks!

@haashem
Copy link
Author

haashem commented Mar 22, 2021

Hi @felangel,
Thanks a lot for supporting Flutter community,
I'm using mocktail: ^0.1.1
I have updated the sample code. create a test file in test folder and paste the above code.
Then enable All Exceptions breakpoint in Debugger panel.
and debug test. you will see the exception.

Screen Shot 2021-03-22 at 20 22 07

@felangel
Copy link
Owner

felangel commented Mar 22, 2021

@haashem that is expected because you have enabled All Exceptions. mocktail handles the TypeError internally. I would recommend changing your VSCode debugger settings to Unhandled Exceptions. The test should pass if you press continue.

@haashem
Copy link
Author

haashem commented Mar 22, 2021

Great for hint, I saw even with that issue most of my tests passed, but still a few I them complaining, issuing the same error!
I will provide my real test in another post.
Screen Shot 2021-03-22 at 20 31 02

@haashem
Copy link
Author

haashem commented Mar 22, 2021

Here is the real demo:

Add dependencies:
firebase_auth: ^1.0.1
mocktail: ^0.1.1

IAuthFacade:

import 'package:firebase_auth/firebase_auth.dart';

abstract class IAuthFacade {
  Future<String> signInWithEmailAndPassword(
      {required String email, required String password});
}

class FirebaseAuthFacade implements IAuthFacade {
  final FirebaseAuth _firebaseAuth;

  FirebaseAuthFacade(this._firebaseAuth);
  @override
  Future<String> signInWithEmailAndPassword(
      {required String email, required String password}) async {
    try {
      final userCredentails = await _firebaseAuth.signInWithEmailAndPassword(
          email: email, password: password);

      return userCredentails.credential!.token.toString();
    } on FirebaseAuthException catch (e) {
      throw Exception('Login Error');
    }
  }
}

Test case:

import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';
import 'package:mocktail_issue/firebase_auth_facade.dart';

class MockFirebaseAuth extends Mock implements FirebaseAuth {}

class MockAuthResult extends Mock implements UserCredential {}
void main() {
  
  late MockFirebaseAuth mockFirebaseAuth;
  late FirebaseAuthFacade authFacade;

  setUp(() {
    mockFirebaseAuth = MockFirebaseAuth();
    authFacade = FirebaseAuthFacade(mockFirebaseAuth);
  });

  group('Sign in', () {
    test('should signin user when credentials are valid', () async {
      when(() => mockFirebaseAuth.signInWithEmailAndPassword(
          email: 'sad',
          password: 'asd')).thenAnswer((_) async => MockAuthResult());

      final result = await authFacade.signInWithEmailAndPassword(
          email: '', password: '');

      expect(result, 'userToken');
      verify(() => mockFirebaseAuth.signInWithEmailAndPassword(
          email: 'asd', password: 'ads')).called(1);
    });
  });
}

another issue I have in previous I had not to pass dump strings to methods,

test('should signin user when credentials are valid', () async {
      when(mockFirebaseAuth!)
          .calls(#signInWithEmailAndPassword)
          .thenAnswer((_) async => MockAuthResult());

      final result = await authFacade!
          .signInWithEmailAndPassword(email: email, password: password);

      expect(result, const Right(unit));
      verify(mockFirebaseAuth!).called(#signInWithEmailAndPassword).once();
    });

It was much simpler and makes sense, It was not matter the value for parameters, but with new syntax I had to provide dump values! any reason for this change?

@resfandiari
Copy link

Hi, @felangel thanks for the best package.
I have the same error and some of my tests failed. how can I change android studio debugger settings to Unhandled Exceptions?

@haashem
Copy link
Author

haashem commented Apr 17, 2021

@felangel Is there any update? or any bottlenecks?

@felangel
Copy link
Owner

Hi @haashem 👋
Sorry for the delayed response!

I believe the issue with your test is the values for the parameters you are providing in the stub don't match the values of the parameters being provided when the method is being called. This change was made to align with how mockito works.

If you want the stub to match any parameter you can use the any() matcher in mocktail.

import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';
import 'package:mocktail_issue/firebase_auth_facade.dart';

class MockFirebaseAuth extends Mock implements FirebaseAuth {}

class MockAuthResult extends Mock implements UserCredential {}
void main() {
  
  late MockFirebaseAuth mockFirebaseAuth;
  late FirebaseAuthFacade authFacade;

  setUp(() {
    mockFirebaseAuth = MockFirebaseAuth();
    authFacade = FirebaseAuthFacade(mockFirebaseAuth);
  });

  group('Sign in', () {
    test('should signin user when credentials are valid', () async {
      when(() => mockFirebaseAuth.signInWithEmailAndPassword(
          email: any(named: 'email'),
          password: any(named: 'password'))).thenAnswer((_) async => MockAuthResult());

      final result = await authFacade.signInWithEmailAndPassword(
          email: '', password: '');

      expect(result, 'userToken');
      verify(() => mockFirebaseAuth.signInWithEmailAndPassword(
          email: 'asd', password: 'ads')).called(1);
    });
  });
}

Hope that helps 👍

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

No branches or pull requests

4 participants