Felipe Augusto
Felipe Augusto

Reputation: 8184

Bad state: Mock method was not called within `when()`. Was a real method called?

I'm trying to make a mock of an httpRequest in flutter using mockito.

Here I define a global http client:

library utgard.globals;

import 'package:http/http.dart' as http;

http.Client httpClient = http.Client();

Then I replace in integration testing:

import 'package:flutter_driver/driver_extension.dart';
import 'package:http/http.dart' as http;
import 'package:utgard/globals.dart' as globals;
import 'package:mockito/mockito.dart';

import 'package:utgard/main.dart' as app;

class MockClient extends Mock implements http.Client {}

void main() {
  final MockClient client = MockClient();
  globals.httpClient = client;

  enableFlutterDriverExtension();

  app.main();
}

Then I try to use when of mockito:

test('login with correct password', () async {
      final client = MockClient();

      when(globals.httpClient.post('http://www.google.com'))
          .thenAnswer((_) async => http.Response('{"title": "Test"}', 200));

      await driver.enterText('000000');
      await driver.tap(loginContinuePasswordButton);
    });

But I receive the following error:

Bad state: Mock method was not called within when(). Was a real method called?

Upvotes: 41

Views: 28483

Answers (4)

ary boby
ary boby

Reputation: 1

please declare resetMocktailState() in teardown or at the end of setup, so the test cases should not affect later test cases.

Upvotes: 0

Rahul
Rahul

Reputation: 243

There is one more possibility. If this happens to your mock object, then probably it may be outdated. In this case, try regenerating your mock objects by using

flutter pub run build_runner build --delete-conflicting-outputs

Upvotes: 3

Andrey Gordeev
Andrey Gordeev

Reputation: 32529

This issue may happen when you implement a method you want to mock instead of letting Mockito do that.

This code below will return Bad state: Mock method was not called within when(). Was a real method called?:

class MockFirebaseAuth extends Mock implements FirebaseAuth {
  FirebaseUser _currentUser;

  MockFirebaseAuth(this._currentUser);

  // This method causes the issue.
  Future<FirebaseUser> currentUser() async {
    return _currentUser;
  }
}

final user = MockFirebaseUser();
final mockFirebaseAuth = MockFirebaseAuth(user);

// Will throw `Bad state: Mock method was not called within `when()`. Was a real method called?`
when(mockFirebaseAuth.currentUser())
    .thenAnswer((_) => Future.value(user));

What do you want instead is:

class MockFirebaseAuth extends Mock implements FirebaseAuth {}

final user = MockFirebaseUser();
final mockFirebaseAuth = MockFirebaseAuth();

// Will work as expected
when(mockFirebaseAuth.currentUser())
    .thenAnswer((_) => Future.value(user));

Also this issue happens when you try to call when() on a non-mock sublass:

class MyClass {
  String doSomething() {
    return 'test';
  }
}

final myClassInstance = MyClass();

// Will throw `Bad state: Mock method was not called within `when()`. Was a real method called?`
when(myClassInstance.doSomething())
    .thenReturn((_) => 'mockedValue');

Upvotes: 52

Felipe Augusto
Felipe Augusto

Reputation: 8184

The solution I found was to define the mock in test_driver/app.dart and call the runApp function after that, this way you can apply the mock even with flutter integration testing:

import 'package:flutter/widgets.dart';
import 'package:flutter_driver/driver_extension.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:utgard/business/config/globals.dart';
import 'package:utgard/main.dart' as app;

class MockClient extends Mock implements http.Client {}

void main() {
  enableFlutterDriverExtension();

  final MockClient client = MockClient();
  // make your mocks here
  httpClient = client;

  runApp(app.MyApp());
}

Since it can become a huge code to mock all the requests there you can make a separate function in order to better organize the code:

import 'package:flutter/widgets.dart';
import 'package:flutter_driver/driver_extension.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:utgard/business/config/globals.dart';
import 'package:utgard/main.dart' as app;

class MockClient extends Mock implements http.Client {}

void main() {
  enableFlutterDriverExtension();

  final MockClient client = MockClient();
  makeMock();
  httpClient = client;

  runApp(app.MyApp());
}

Upvotes: -2

Related Questions