flutter 错误状态:未在“when()”中调用模拟方法,是否调用了真实的方法?

kb5ga3dv  于 2023-02-13  发布在  Flutter
关注(0)|答案(4)|浏览(165)

我正在尝试使用mockito模拟flutter中的httpRequest
这里我定义了一个全局http客户端:

library utgard.globals;

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

http.Client httpClient = http.Client();

然后在集成测试中替换:

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

然后我尝试使用mockito的when

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);
    });

但我收到以下错误:
错误状态:未在when()中调用模拟方法。是否调用了真实的方法?

nhaq1z21

nhaq1z211#

当您实现一个想要模拟的方法而不是让Mockito来模拟时,可能会发生这个问题。
下面的代码将返回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));

你想要的是:

class MockFirebaseAuth extends Mock implements FirebaseAuth {}

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

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

当你尝试在一个非mock子类上调用when()时,也会发生这个问题

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');
0lvr5msh

0lvr5msh2#

还有一种可能性。如果你的模拟对象发生这种情况,那么它可能已经过时了。在这种情况下,尝试使用

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

xxe27gdn3#

请在拆卸或设置结束时声明resetMocktailState(),因此测试用例不应影响后续测试用例。

w80xi6nr

w80xi6nr4#

我找到的解决方案是在 test_driver/app.dart 中定义模拟,然后调用runApp函数,这样即使在flutter集成测试中也可以应用模拟:

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

由于模拟所有请求可能会变成一个巨大的代码,因此您可以创建一个单独的函数,以便更好地组织代码:

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

相关问题