Lubię symulować asynchroniczne wywołanie usługi internetowej w mojej aplikacji Dart do testowania. Aby zasymulować losowość tych próbnych wywołań odpowiadających (prawdopodobnie nie w kolejności), chciałbym zaprogramować moje makiety tak, aby czekały (spały) przez określony czas, zanim zwrócą „Przyszłość”.
Jak mogę to zrobić?
unit-testing
mocking
dart
Vinnie
źródło
źródło
() => "1"
?await sleep1();
Edycja 2019:
W kodzie asynchronicznym
await Future.delayed(Duration(seconds: 1));
W kodzie synchronizacji
import 'dart:io'; sleep(Duration(seconds:1));
Uwaga: Spowoduje to zablokowanie całego procesu (izolację), więc inne funkcje asynchroniczne nie będą przetwarzane. Nie jest również dostępny w Internecie, ponieważ JavaScript jest tak naprawdę tylko asynchroniczny.
źródło
sleep()
całkowicie blokuje cały izolat. Żaden kod Dart w ogóle nie będzie działał podczas snu. Prawdopodobnie kompiluje się do czegoś podobnego do C ++std::this_thread::sleep_for
.Future.delayed()
planuje późniejsze wznowienie funkcji asynchronicznej, ale następnie zwraca sterowanie do pętli zdarzeń Dart, aby inne funkcje asynchroniczne mogły nadal działać.Nie zawsze jest to to, czego chcesz (czasami chcesz
Future.delayed
), ale jeśli naprawdę chcesz spać w aplikacji wiersza poleceń Dart, możesz użyć dart: io'ssleep()
:import 'dart:io'; main() { sleep(const Duration(seconds:1)); }
źródło
await sleep()
i spodziewam się innych zadań podczas snu :(Odkryłem, że istnieje kilka implementacji w Dart, aby wykonać opóźnienie kodu:
new Future.delayed(const Duration(seconds: 1)); //recommend new Timer(const Duration(seconds: 1), ()=>print("1 second later.")); sleep(const Duration(seconds: 1)); //import 'dart:io'; new Stream.periodic(const Duration(seconds: 1), (_) => print("1 second later.")).first.then((_)=>print("Also 1 second later.")); //new Stream.periodic(const Duration(seconds: 1)).first.then((_)=>print("Also 1 second later."));
źródło
Dla składni Dart 2+, w kontekście funkcji asynchronicznej:
import 'package:meta/meta.dart'; //for @required annotation void main() async { void justWait({@required int numberOfSeconds}) async { await Future.delayed(Duration(seconds: numberOfSeconds)); } await justWait(numberOfSeconds: 5); }
źródło
To przydatna makieta, która może przyjmować opcjonalny parametr, aby mockować błąd:
Future _mockService([dynamic error]) { return new Future.delayed(const Duration(seconds: 2), () { if (error != null) { throw error; } }); }
Możesz go używać w ten sposób:
await _mockService(new Exception('network error'));
źródło
Musiałem również poczekać na zakończenie usługi podczas testu jednostkowego. Zaimplementowałem w ten sposób:
void main() { test('Send packages using isolate', () async { await SendingService().execute(); }); // Loop to the amount of time the service will take to complete for( int seconds = 0; seconds < 10; seconds++ ) { test('Waiting 1 second...', () { sleep(const Duration(seconds:1)); } ); } } ... class SendingService { Isolate _isolate; Future execute() async { ... final MyMessage msg = new MyMessage(...); ... Isolate.spawn(_send, msg) .then<Null>((Isolate isolate) => _isolate = isolate); } static void _send(MyMessage msg) { final IMyApi api = new IMyApi(); api.send(msg.data) .then((ignored) { ... }) .catchError((e) { ... } ); } }
źródło