【问题标题】:Bad state: Mock method was not called within `when()`. Was a real method called?错误状态:在 `when()` 中未调用 Mock 方法。是否调用了真正的方法?
【发布时间】:2019-08-20 19:35:40
【问题描述】:

我正在尝试使用 mockito 在颤振中模拟 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();
}

然后我尝试使用 when 的 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);
    });

但我收到以下错误:

错误状态:未在 when() 内调用模拟方法。是否调用了真正的方法?

【问题讨论】:

    标签: dart flutter mockito flutter-test


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

      当您实现要模拟的方法而不是让 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));
      

      当您尝试在非模拟子类上调用 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');
      

      【讨论】:

      • 在我的例子中,我想模拟 toString(),这样我可以更清楚地看到错误,不仅仅是类名,而且 toString() 已经从 Mock 本身定义。
      【解决方案3】:

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

      重新生成模拟对象
      flutter pub run build_runner build --delete-conflicting-outputs
      

      【讨论】:

        猜你喜欢
        • 2018-09-10
        • 2021-04-12
        • 1970-01-01
        • 2015-10-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-01-25
        相关资源
        最近更新 更多