测试在 Isolate 上运行代码的 Dart class
Testing Dart class that runs code on Isolate
我有一个在 Isolate 上执行计算的 Dart class。这是我的代码:
class Mapper {
SendPort _isolateSendPort;
Isolate _isolate;
Mapper() {
_asyncInit();
}
void _asyncInit() async {
final receivePort = ReceivePort();
_isolate = await Isolate.spawn(
_mappingFunction,
receivePort.sendPort,
);
_isolateSendPort = await receivePort.first;
}
static void _mappingFunction(SendPort callerSendPort) {
final newIsolateReceivePort = ReceivePort();
callerSendPort.send(newIsolateReceivePort.sendPort);
newIsolateReceivePort.listen((dynamic message) {
final crossIsolatesMessage =
message as CrossIsolatesMessage<Input>;
// some computations...
crossIsolatesMessage.sender.send(output);
});
}
Future<Output> map(Input input) async {
final port = ReceivePort();
_isolateSendPort.send(CrossIsolatesMessage<Input>(
sender: port.sendPort,
message: input,
));
return port.map((event) => event as Output).first;
}
void dispose() {
_isolate?.kill(priority: Isolate.immediate);
_isolate = null;
}
}
class CrossIsolatesMessage<T> {
final SendPort sender;
final T message;
CrossIsolatesMessage({
@required this.sender,
this.message,
});
}
此代码在我 运行 Flutter 应用程序时运行良好。但是 public 方法 Future<Output> map(Input input)
的单元测试抛出一个错误 NoSuchMethodError
这意味着 _isolateSendPort
是空的。
单元测试代码如下:
test('Mapper map', () {
final sut = Mapper();
final inputDummy = Input('123');
final resultFuture = sut.map(inputDummy);
final expectedResult = Output('321');
expectLater(resultFuture, completion(expectedResult));
});
这是一个错误:
NoSuchMethodError: The method 'send' was called on null.
Receiver: null
Tried calling: send(Instance of 'CrossIsolatesMessage<Input>')
dart:core Object.noSuchMethod
为什么在测试中出现这个错误?为此 class 编写测试的正确方法是什么?
问题已解决。
创建 _isolate
和 _isolateSendPort
是一个异步操作。这就是 _isolateSendPort
在测试中为 null 的原因。从 Mapper
构造函数调用方法 _asyncInit()
是创建隔离的错误方法。
这是使用惰性隔离初始化的工作解决方案:
class Mapper {
SendPort _isolateSendPort;
Isolate _isolate;
void _initIsolate() async {
final receivePort = ReceivePort();
_isolate = await Isolate.spawn(
_mappingFunction,
receivePort.sendPort,
);
_isolateSendPort = await receivePort.first;
}
...
Future<Output> map(Input input) async {
final port = ReceivePort();
if (_isolateSendPort == null) {
await _initIsolate();
}
_isolateSendPort.send(CrossIsolatesMessage<Input>(
sender: port.sendPort,
message: input,
));
return port.map((event) => event as Output).first;
}
...
}
我有一个在 Isolate 上执行计算的 Dart class。这是我的代码:
class Mapper {
SendPort _isolateSendPort;
Isolate _isolate;
Mapper() {
_asyncInit();
}
void _asyncInit() async {
final receivePort = ReceivePort();
_isolate = await Isolate.spawn(
_mappingFunction,
receivePort.sendPort,
);
_isolateSendPort = await receivePort.first;
}
static void _mappingFunction(SendPort callerSendPort) {
final newIsolateReceivePort = ReceivePort();
callerSendPort.send(newIsolateReceivePort.sendPort);
newIsolateReceivePort.listen((dynamic message) {
final crossIsolatesMessage =
message as CrossIsolatesMessage<Input>;
// some computations...
crossIsolatesMessage.sender.send(output);
});
}
Future<Output> map(Input input) async {
final port = ReceivePort();
_isolateSendPort.send(CrossIsolatesMessage<Input>(
sender: port.sendPort,
message: input,
));
return port.map((event) => event as Output).first;
}
void dispose() {
_isolate?.kill(priority: Isolate.immediate);
_isolate = null;
}
}
class CrossIsolatesMessage<T> {
final SendPort sender;
final T message;
CrossIsolatesMessage({
@required this.sender,
this.message,
});
}
此代码在我 运行 Flutter 应用程序时运行良好。但是 public 方法 Future<Output> map(Input input)
的单元测试抛出一个错误 NoSuchMethodError
这意味着 _isolateSendPort
是空的。
单元测试代码如下:
test('Mapper map', () {
final sut = Mapper();
final inputDummy = Input('123');
final resultFuture = sut.map(inputDummy);
final expectedResult = Output('321');
expectLater(resultFuture, completion(expectedResult));
});
这是一个错误:
NoSuchMethodError: The method 'send' was called on null.
Receiver: null
Tried calling: send(Instance of 'CrossIsolatesMessage<Input>')
dart:core Object.noSuchMethod
为什么在测试中出现这个错误?为此 class 编写测试的正确方法是什么?
问题已解决。
创建 _isolate
和 _isolateSendPort
是一个异步操作。这就是 _isolateSendPort
在测试中为 null 的原因。从 Mapper
构造函数调用方法 _asyncInit()
是创建隔离的错误方法。
这是使用惰性隔离初始化的工作解决方案:
class Mapper {
SendPort _isolateSendPort;
Isolate _isolate;
void _initIsolate() async {
final receivePort = ReceivePort();
_isolate = await Isolate.spawn(
_mappingFunction,
receivePort.sendPort,
);
_isolateSendPort = await receivePort.first;
}
...
Future<Output> map(Input input) async {
final port = ReceivePort();
if (_isolateSendPort == null) {
await _initIsolate();
}
_isolateSendPort.send(CrossIsolatesMessage<Input>(
sender: port.sendPort,
message: input,
));
return port.map((event) => event as Output).first;
}
...
}