Mockito - 在空安全迁移之后存根一个方法
Mockito - stub a method after the null-safety migration
在空安全之前,我可以简单地模拟 sendRequest(...) 方法:
void stubBaseRepositorySendRequestResponse(String response) {
when(baseRepository.sendRequest(onGetData: anyNamed('onGetData')))
.thenAnswer((_) {
return Future<String>.value(response);
});
}
这个方法的签名是:
Future<T> sendRequest<T>({required Future<T> Function() onGetData})
如何使用新的空安全版本的 mockito 完成此操作?
我是否仍然可以保持此存根的通用特性并允许传入任何参数?
这可以通过 mocktail 轻松完成。
更容易,没有 mockito 所需的代码生成。
首先导入 mocktail 很重要:
import 'package:mocktail/mocktail.dart';
然后创建我们要模拟的 class 的模拟:
class MockBaseRepository extends Mock implements BaseRepository {}
void stubBaseRepositorySendRequestResponse(String response) {
when(() => baseRepository.sendRequest(
onGetData: any(named: 'onGetData', that: isNotNull))).thenAnswer((_) {
return Future<String>.value(response);
});
}
在 mockito 空安全升级后更新存根:
为了概述这个过程,需要生成存根 class,这是使用 build_runner
包完成的。您将需要导入 class 和存根所需的方法。
- 更新 class - 从存根定义中删除 'Mock',因为导入的存根 class 将以 'Mock' 开头,例如:
class MyClass extends Mock implements MyClassBase {}
而不是
class MockMyClass extends Mock implements MyClassBase {}
- 在 main 之前添加
@GenerateMocks([MockedClass])
例如 @GenerateMocks([MyClass])
(需要导入:import 'package:mockito/annotations.dart';
)
- 安装build_runner
- 通过 运行ning
生成存根 class
flutter pub run build_runner build --delete-conflicting-outputs
- 在你的测试文件中导入存根class,它将在你的测试文件相同的目录中生成,导入看起来像
import '{TEST_FILE_NAME}.mocks.dart';
。现在可以使用存根 class,其名称与 Generate(
中以 Mock
开头的名称相同,例如 MockMyClass
- 存根所需方法,在call/assertion之前(提供参数和return值):
when(mockMyClass.someFancyMethod(any, any))
.thenAnswer((_) => Future.value(null));
PS
以这种方式模拟 NavigatorObserver 时遇到问题,我得到的错误:
The following MissingStubError was thrown building IconTheme(color: Color(0xdd000000)): 'navigator'
用 NavigatorState
存根 navigator
没有帮助,我猜这与上下文传播有关。
我使用以下非空安全方式解决了这个问题,如 mockito's null-safety guideline 中所指定:
@GenerateMocks([],
customMocks: [
MockSpec<NavigatorObserver>(returnNullOnMissingStub: true)
])
之后运行
flutter pub run build_runner build --delete-conflicting-outputs
它将通过导入 *.mocks.dart
文件(如上所述)产生 MockNavigatorObserver
。当然,因为它是由 mockito 生成的,所以需要删除 class.
的任何自定义定义
在空安全之前,我可以简单地模拟 sendRequest(...) 方法:
void stubBaseRepositorySendRequestResponse(String response) {
when(baseRepository.sendRequest(onGetData: anyNamed('onGetData')))
.thenAnswer((_) {
return Future<String>.value(response);
});
}
这个方法的签名是:
Future<T> sendRequest<T>({required Future<T> Function() onGetData})
如何使用新的空安全版本的 mockito 完成此操作? 我是否仍然可以保持此存根的通用特性并允许传入任何参数?
这可以通过 mocktail 轻松完成。 更容易,没有 mockito 所需的代码生成。
首先导入 mocktail 很重要:
import 'package:mocktail/mocktail.dart';
然后创建我们要模拟的 class 的模拟:
class MockBaseRepository extends Mock implements BaseRepository {}
void stubBaseRepositorySendRequestResponse(String response) {
when(() => baseRepository.sendRequest(
onGetData: any(named: 'onGetData', that: isNotNull))).thenAnswer((_) {
return Future<String>.value(response);
});
}
在 mockito 空安全升级后更新存根:
为了概述这个过程,需要生成存根 class,这是使用 build_runner
包完成的。您将需要导入 class 和存根所需的方法。
- 更新 class - 从存根定义中删除 'Mock',因为导入的存根 class 将以 'Mock' 开头,例如:
class MyClass extends Mock implements MyClassBase {}
而不是
class MockMyClass extends Mock implements MyClassBase {}
- 在 main 之前添加
@GenerateMocks([MockedClass])
例如@GenerateMocks([MyClass])
(需要导入:import 'package:mockito/annotations.dart';
) - 安装build_runner
- 通过 运行ning 生成存根 class
flutter pub run build_runner build --delete-conflicting-outputs
- 在你的测试文件中导入存根class,它将在你的测试文件相同的目录中生成,导入看起来像
import '{TEST_FILE_NAME}.mocks.dart';
。现在可以使用存根 class,其名称与Generate(
中以Mock
开头的名称相同,例如MockMyClass
- 存根所需方法,在call/assertion之前(提供参数和return值):
when(mockMyClass.someFancyMethod(any, any))
.thenAnswer((_) => Future.value(null));
PS
以这种方式模拟 NavigatorObserver 时遇到问题,我得到的错误:
The following MissingStubError was thrown building IconTheme(color: Color(0xdd000000)): 'navigator'
用 NavigatorState
存根 navigator
没有帮助,我猜这与上下文传播有关。
我使用以下非空安全方式解决了这个问题,如 mockito's null-safety guideline 中所指定:
@GenerateMocks([],
customMocks: [
MockSpec<NavigatorObserver>(returnNullOnMissingStub: true)
])
之后运行
flutter pub run build_runner build --delete-conflicting-outputs
它将通过导入 *.mocks.dart
文件(如上所述)产生 MockNavigatorObserver
。当然,因为它是由 mockito 生成的,所以需要删除 class.