Как имитировать клиент Socket.io в тестах Flutter

avatar
Eranga Heshan
1 июля 2021 в 18:25
555
0
5

Я использую socket_io_client v0.9.12 в своем приложении флаттера (до сих пор не использую нулевую безопасность). Я создаю сокетное соединение с моим внутренним сервером при запуске приложения и разрешаю дочерним виджетам доступ к нему с помощью провайдера.

Я пытаюсь начать создавать соединение в конструкторе, чтобы, когда мне нужно будет использовать клиент сокета, он, вероятно, уже был инициализирован.

Это мой класс провайдера, в котором создано подключение к сокету:

class SocketClient {
  SocketClient() {
    _initializer = initialize();
  }

  Future _initializer;

  /// Socket client
  Socket client;

  /// Wait until the client is properly connected with the server
  Future finishInitializing() => _initializer;

  /// Initialize the socket connection with the server
  Future initialize() async {
    final completer = Completer<Socket>();

    final socket = io(
      'http://localhost:3000/gateway',
      OptionBuilder() //
          .setTransports(['websocket'])
          .disableAutoConnect()
          .setQuery({'token': 'TOKEN'})
          .build(),
    )..connect();

    socket
      ..onConnect((_) {
        completer.complete(socket);
      });

    client = await completer.future;
  }
}

Виджет основного приложения, который у меня есть:

@override
Widget build(BuildContext context) {
  return Provider<SocketClient>(
    create: (_) => SocketClient(),
    builder: (context, _) {
      return Scaffold(
          ...
      );
    },
  );
}

Вот как я пытаюсь использовать клиент сокета:

Future<void> foo(SocketClient socketClient) async {
  await socketClient.finishInitializing();
  final socket = socketClient.client;
  socket.on(eventName, (dynamic uploadDrawingEvent) {
    ...
  });
}

До сих пор все работает нормально. ????

Однако, когда я пытаюсь запустить тесты, зависящие от этого сокет-клиента, я вижу следующую ошибку:

Pending timers:
Timer (duration: 0:00:20.000000, periodic: false), created:
#0      new FakeTimer._ (package:fake_async/fake_async.dart:284:41)
#1      FakeAsync._createTimer (package:fake_async/fake_async.dart:248:27)
#2      FakeAsync.run.<anonymous closure> (package:fake_async/fake_async.dart:181:19)
#5      Manager.connect (package:socket_io_client/src/manager.dart:232:19)
#6      Manager.open (package:socket_io_client/src/manager.dart:194:41)
#7      Socket.connect (package:socket_io_client/src/socket.dart:104:8)
#8      SocketClient.initialize (package:flutter_app/web/services/socket_provider.dart:48:8)
<asynchronous suspension>
(elided 2 frames from dart:async)

══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following assertion was thrown running a test:
A Timer is still pending even after the widget tree was disposed.
'package:flutter_test/src/binding.dart':
Failed assertion: line 1241 pos 12: '!timersPending'

When the exception was thrown, this was the stack:
#2      AutomatedTestWidgetsFlutterBinding._verifyInvariants (package:flutter_test/src/binding.dart:1241:12)
#3      TestWidgetsFlutterBinding._runTestBody (package:flutter_test/src/binding.dart:803:7)
<asynchronous suspension>
(elided 2 frames from class _AssertionError)
...
Функция

initialize продолжает висеть после строки client = await completer.future;. Это будущее не решено даже после завершения теста (см. ошибку).

Я хотел бы получить идеи о том, как правильно имитировать этот клиент сокета, чтобы избежать этой ошибки.

Я больше склоняюсь к ответу, который издевается над функциональностью клиента сокета, потому что мне нужно написать еще несколько тестов, чтобы охватить обработчики событий.

Заранее спасибо! ????

Источник
Durul Dalkanat
22 апреля 2022 в 19:45
0

Есть ли у вас дальше? столкнулся с той же проблемой

Eranga Heshan
26 апреля 2022 в 02:22
0

К сожалению нет. На данный момент мы написали тесты, используя фиктивный клиент сокета, используя mocktail. Мы предоставляем этот имитированный клиент сокета в виджет при запуске тестов.

Ответы (0)