felangel / felangel/mocktail

can not send a mock object to an isolate

Offen
#249 0 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen
enhancement
Vorherrschende Sprache
Dart
Sterne
702
Forks
88
PR-Merge-Kennzahlen
Keine gemergten PRs in 30 T.

Beschreibung

**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)

```

Beitragsleitfaden

Für dieses Repository ist kein Beitragsleitfaden indexiert

Bewertung

Dieses Issue wurde noch nicht bewertet.

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.