felangel / felangel/mocktail

can not send a mock object to an isolate

Đang mở
#249 0 bình luận 0 reaction 0 người được giao Xem trên GitHub
enhancement
Ngôn ngữ chính
Dart
Star
702
Fork
88
Chỉ số merge pull request
Không có pull request nào được merge trong 30 ngày

Mô tả

**Describe the bug**
I have a piece of code that downloads some resources from internet and saves it local disk. Download operation is performed on a separate isolate. I wrote some tests and wanted to test the case when network drops while downloading. In order to do that, I used some mock objects. When I tried to send a mock object to isolate, I got an error. See below please.

In order to reproduce the problem, I created a brand new project. I am attaching the pubspec.yaml and source files.

**To Reproduce**
**/pubspec.yaml**
```

name: mock_in_isolate
description: A sample command-line application.
version: 1.0.0
# repository: https://github.com/my_org/my_repo

environment:
sdk: ^3.3.1

# Add regular dependencies here.
dependencies:
http: ^1.2.2
mocktail: ^1.0.4
# path: ^1.8.0

dev_dependencies:
lints: ^4.0.0
test: ^1.24.0
```

**/bin/mock_in_isolate.dart**
```
import 'package:mock_in_isolate/isolated_downloader.dart' as iso_down;
import 'package:mock_in_isolate/mock_in_isolate.dart' as mock_in_isolate;

void main(List arguments) {
print('Hello world: ${mock_in_isolate.calculate()}!');
iso_down.IsolatedDownloader dwn = iso_down.IsolatedDownloader();
dwn.startDownload();
}
```

**/lib/isolated_downlaod.dart**
```
import 'dart:isolate';

import 'package:http/http.dart' as im_http;
import 'package:mocktail/mocktail.dart' as im_mock;

class MockHttpClient extends im_mock.Mock implements im_http.Client {}

class MockStreamedResponse extends im_mock.Mock
implements im_http.StreamedResponse {}

class FakeBaseRequest extends im_mock.Fake implements im_http.BaseRequest {}

Future downloadInIsolate(SendPort senderPOrtOnIsolate) async {
final receiverOnChild = ReceivePort();
senderPOrtOnIsolate.send(receiverOnChild.sendPort);

receiverOnChild.listen((Object? msg) async {
if (msg is im_http.Client) {
im_http.Client client = msg;
im_http.Response response = await client.get(Uri.http('google.com'));
senderPOrtOnIsolate.send(response.statusCode);
}
});
}

class IsolatedDownloader {
final receiverPortOnMain = ReceivePort();
SendPort? sendPortOnMain;
Isolate? downloadIsolate;

Future startDownload() async {
if (downloadIsolate != null) return;

MockHttpClient client = MockHttpClient();
im_http.StreamedResponse streamedResponse = MockStreamedResponse();

im_mock.registerFallbackValue(FakeBaseRequest());
im_mock
.when(() => client.send(im_mock.any()))
.thenAnswer((invocation) async => streamedResponse);

im_mock.when(() => streamedResponse.statusCode).thenReturn(
await Future.delayed(const Duration(seconds: 2), () => 502));

downloadIsolate = await Isolate.spawn(
downloadInIsolate, receiverPortOnMain.sendPort);

receiverPortOnMain.listen((Object? msgFromIsolate) async {
print('Message from Child: $msgFromIsolate');
if (msgFromIsolate is int) {
print('response.statusCode: $msgFromIsolate');
dispose();
} else if (msgFromIsolate is SendPort) {
sendPortOnMain = msgFromIsolate;
sendPortOnMain?.send(client);
}
});
}

void dispose() {
receiverPortOnMain.close();
downloadIsolate?.kill();
downloadIsolate = null;
}
}

Future main() async {
final id = IsolatedDownloader();
await id.startDownload();
}
```

1. cd /tmp
2. dart create mock_in_isolate
3. cd mock_in_isolate
4. dart pub add http
5. dart pub add mocktail
6. copy above files into proper folders
7. dart run

**Expected behavior**
I should be able to send a mock object to an isolate (hopefully)

**Screenshots**
Not a GUI app, so no need for screenshots I guess.

**Logs **
dart analyze
Analyzing mock_in_isolate... 0.6s
No issues found!

flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.19.3, on Ubuntu 22.04.5 LTS 6.8.0-45-generic, locale
en_US.UTF-8)
[✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
[✓] Chrome - develop for the web
[✓] Linux toolchain - develop for Linux desktop
[✓] Android Studio (version 2022.3)
[✓] VS Code (version 1.94.2)
[✓] Connected device (2 available)
[✓] Network resources

**Additional context**
output of the program when I run it by ```dart run```

```
building package executable...
Built mock_in_isolate:mock_in_isolate.
Hello world: 42!
Message from Child: SendPort
Unhandled exception:
Invalid argument(s): Illegal argument in isolate message: object is unsendable - Library:'dart:isolate' Class: _ReceivePortImpl@1026248 (see restrictions listed at `SendPort.send()` documentation for more information)
<- receiverPortOnMain in Instance of 'IsolatedDownloader' (from package:mock_in_isolate/isolated_downloader.dart)
<- Context num_variables: 3 <- Closure: (Invocation) => Future (from package:mock_in_isolate/isolated_downloader.dart)
<- Instance of 'Expectation>' (from package:mocktail/src/mocktail.dart)
<- _List len:3 (from dart:core)
<- Instance(length:1) of '_GrowableList' (from dart:core)
<- Instance of 'MockHttpClient' (from package:mock_in_isolate/isolated_downloader.dart)

#0 _SendPort._sendInternal (dart:isolate-patch/isolate_patch.dart:250:43)
#1 _SendPort.send (dart:isolate-patch/isolate_patch.dart:231:5)
#2 IsolatedDownloader.startDownload. (package:mock_in_isolate/isolated_downloader.dart:55:25)
#3 _RootZone.runUnaryGuarded (dart:async/zone.dart:1594:10)
#4 _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:339:11)
#5 _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7)
#6 _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:784:19)
#7 _StreamController._add (dart:async/stream_controller.dart:658:7)
#8 _StreamController.add (dart:async/stream_controller.dart:606:5)
#9 _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:184:12)

```

Hướng dẫn đóng góp

Chưa lập chỉ mục được hướng dẫn đóng góp cho kho mã nguồn này

Đánh giá

Issue này chưa được đánh giá.

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.