Ejemplo n.º 1
0
class TestGateIoAPIOrderBookDataSource(unittest.TestCase):
    @classmethod
    def setUpClass(cls) -> None:
        super().setUpClass()
        cls.ev_loop = asyncio.get_event_loop()
        cls.base_asset = "COINALPHA"
        cls.quote_asset = "HBOT"
        cls.trading_pair = f"{cls.base_asset}-{cls.quote_asset}"

    def setUp(self) -> None:
        super().setUp()
        self.mocking_assistant = NetworkMockingAssistant()
        self.throttler = AsyncThrottler(CONSTANTS.RATE_LIMITS)
        self.data_source = GateIoAPIOrderBookDataSource(
            self.throttler, trading_pairs=[self.trading_pair])

    def async_run_with_timeout(self, coroutine: Awaitable, timeout: int = 1):
        ret = self.ev_loop.run_until_complete(
            asyncio.wait_for(coroutine, timeout))
        return ret

    def get_last_trade_instance_data_mock(self) -> List:
        last_trade_instance_data = [{
            "currency_pair": f"{self.base_asset}_{self.quote_asset}",
            "last": "0.2959",
            "lowest_ask": "0.295918",
            "highest_bid": "0.295898",
            "change_percentage": "-1.72",
            "base_volume": "78497066.828007",
            "quote_volume": "23432064.936692",
            "high_24h": "0.309372",
            "low_24h": "0.286827",
        }]
        return last_trade_instance_data

    @staticmethod
    def get_order_book_data_mock() -> Dict:
        order_book_data = {
            "id": 1890172054,
            "current": 1630644717528,
            "update": 1630644716786,
            "asks": [["0.298705", "5020"]],
            "bids": [["0.298642", "2703.17"]]
        }
        return order_book_data

    def get_trade_data_mock(self) -> Dict:
        trade_data = {
            "time": 1606292218,
            "channel": "spot.trades",
            "event": "update",
            "result": {
                "id": 309143071,
                "create_time": 1606292218,
                "create_time_ms": "1606292218213.4578",
                "side": "sell",
                "currency_pair": f"{self.base_asset}_{self.quote_asset}",
                "amount": "16.4700000000",
                "price": "0.4705000000"
            }
        }
        return trade_data

    def get_order_book_update_mock(self) -> Dict:
        ob_update = {
            "time": 1606294781,
            "channel": "spot.order_book_update",
            "event": "update",
            "result": {
                "t": 1606294781123,
                "e": "depthUpdate",
                "E": 1606294781,
                "s": f"{self.base_asset}_{self.quote_asset}",
                "U": 48776301,
                "u": 48776306,
                "b": [
                    ["19137.74", "0.0001"],
                ],
                "a": [["19137.75", "0.6135"]]
            }
        }
        return ob_update

    def get_order_book_snapshot_mock(self) -> Dict:
        ob_snapshot = {
            "time": 1606295412,
            "channel": "spot.order_book",
            "event": "update",
            "result": {
                "t": 1606295412123,
                "lastUpdateId": 48791820,
                "s": f"{self.base_asset}_{self.quote_asset}",
                "bids": [
                    ["19079.55", "0.0195"],
                ],
                "asks": [
                    ["19080.24", "0.1638"],
                ]
            }
        }
        return ob_snapshot

    @aioresponses()
    def test_get_last_trade_instance(self, mock_api):
        url = f"{CONSTANTS.REST_URL}/{CONSTANTS.TICKER_PATH_URL}"
        regex_url = re.compile(f"^{url}".replace(".",
                                                 r"\.").replace("?", r"\?"))
        resp = self.get_last_trade_instance_data_mock()
        mock_api.get(regex_url, body=json.dumps(resp))

        ret = self.async_run_with_timeout(
            coroutine=GateIoAPIOrderBookDataSource.get_last_traded_prices(
                trading_pairs=[self.trading_pair]))

        self.assertEqual(ret[self.trading_pair], Decimal(resp[0]["last"]))

    @aioresponses()
    def test_fetch_trading_pairs(self, mock_api):
        url = f"{CONSTANTS.REST_URL}/{CONSTANTS.SYMBOL_PATH_URL}"
        resp = [{
            "id": f"{self.base_asset}_{self.quote_asset}"
        }, {
            "id": "SOME_PAIR"
        }]
        mock_api.get(url, body=json.dumps(resp))

        ret = self.async_run_with_timeout(
            coroutine=GateIoAPIOrderBookDataSource.fetch_trading_pairs())

        self.assertTrue(self.trading_pair in ret)
        self.assertTrue("SOME-PAIR" in ret)

    @patch(
        "hummingbot.connector.exchange.gate_io.gate_io_utils.retry_sleep_time")
    @aioresponses()
    def test_get_order_book_data_raises(self, retry_sleep_time_mock, mock_api):
        retry_sleep_time_mock.side_effect = lambda *args, **kwargs: 0
        url = f"{CONSTANTS.REST_URL}/{CONSTANTS.ORDER_BOOK_PATH_URL}"
        regex_url = re.compile(f"^{url}".replace(".",
                                                 r"\.").replace("?", r"\?"))
        resp = ""
        for _ in range(CONSTANTS.API_MAX_RETRIES):
            mock_api.get(regex_url, body=json.dumps(resp), status=500)

        with self.assertRaises(IOError):
            self.async_run_with_timeout(coroutine=GateIoAPIOrderBookDataSource.
                                        get_order_book_data(self.trading_pair))

    @aioresponses()
    def test_get_order_book_data(self, mock_api):
        url = f"{CONSTANTS.REST_URL}/{CONSTANTS.ORDER_BOOK_PATH_URL}"
        regex_url = re.compile(f"^{url}".replace(".",
                                                 r"\.").replace("?", r"\?"))
        resp = self.get_order_book_data_mock()
        mock_api.get(regex_url, body=json.dumps(resp))

        ret = self.async_run_with_timeout(
            coroutine=GateIoAPIOrderBookDataSource.get_order_book_data(
                self.trading_pair))

        self.assertEqual(resp, ret)  # shallow comparison is ok

    @aioresponses()
    def test_get_new_order_book(self, mock_api):
        url = f"{CONSTANTS.REST_URL}/{CONSTANTS.ORDER_BOOK_PATH_URL}"
        regex_url = re.compile(f"^{url}".replace(".",
                                                 r"\.").replace("?", r"\?"))
        resp = self.get_order_book_data_mock()
        mock_api.get(regex_url, body=json.dumps(resp))

        ret = self.async_run_with_timeout(
            coroutine=self.data_source.get_new_order_book(self.trading_pair))

        self.assertTrue(isinstance(ret, OrderBook))

    @patch("websockets.connect", new_callable=AsyncMock)
    def test_listen_for_trades(self, ws_connect_mock):
        ws_connect_mock.return_value = self.mocking_assistant.create_websocket_mock(
        )
        resp = self.get_trade_data_mock()
        self.mocking_assistant.add_websocket_text_message(
            websocket_mock=ws_connect_mock.return_value,
            message=json.dumps(resp))
        output_queue = asyncio.Queue()

        self.ev_loop.create_task(
            self.data_source.listen_for_trades(self.ev_loop, output_queue))
        self.mocking_assistant.run_until_all_text_messages_delivered(
            websocket_mock=ws_connect_mock.return_value)

        self.assertTrue(not output_queue.empty())
        self.assertTrue(isinstance(output_queue.get_nowait(),
                                   OrderBookMessage))

    @patch("websockets.connect", new_callable=AsyncMock)
    def test_listen_for_order_book_diffs_update(self, ws_connect_mock):
        ws_connect_mock.return_value = self.mocking_assistant.create_websocket_mock(
        )
        resp = self.get_order_book_update_mock()
        self.mocking_assistant.add_websocket_text_message(
            websocket_mock=ws_connect_mock.return_value,
            message=json.dumps(resp))
        output_queue = asyncio.Queue()

        self.ev_loop.create_task(
            self.data_source.listen_for_order_book_diffs(
                self.ev_loop, output_queue))
        self.mocking_assistant.run_until_all_text_messages_delivered(
            websocket_mock=ws_connect_mock.return_value)

        self.assertTrue(not output_queue.empty())
        self.assertTrue(isinstance(output_queue.get_nowait(),
                                   OrderBookMessage))

    @patch("websockets.connect", new_callable=AsyncMock)
    def test_listen_for_order_book_diffs_snapshot(self, ws_connect_mock):
        ws_connect_mock.return_value = self.mocking_assistant.create_websocket_mock(
        )
        resp = self.get_order_book_snapshot_mock()
        self.mocking_assistant.add_websocket_text_message(
            websocket_mock=ws_connect_mock.return_value,
            message=json.dumps(resp))
        output_queue = asyncio.Queue()

        self.ev_loop.create_task(
            self.data_source.listen_for_order_book_diffs(
                self.ev_loop, output_queue))
        self.mocking_assistant.run_until_all_text_messages_delivered(
            websocket_mock=ws_connect_mock.return_value)

        self.assertTrue(not output_queue.empty())
        self.assertTrue(isinstance(output_queue.get_nowait(),
                                   OrderBookMessage))

    @aioresponses()
    def test_listen_for_order_book_snapshots(self, mock_api):
        url = f"{CONSTANTS.REST_URL}/{CONSTANTS.ORDER_BOOK_PATH_URL}"
        regex_url = re.compile(f"^{url}".replace(".",
                                                 r"\.").replace("?", r"\?"))
        resp = self.get_order_book_data_mock()
        mock_api.get(regex_url, body=json.dumps(resp))
        output_queue = asyncio.Queue()

        self.ev_loop.create_task(
            self.data_source.listen_for_order_book_snapshots(
                self.ev_loop, output_queue))
        ret = self.async_run_with_timeout(coroutine=output_queue.get())

        self.assertTrue(isinstance(ret, OrderBookMessage))
class KrakenAPIOrderBookDataSourceTest(unittest.TestCase):
    @classmethod
    def setUpClass(cls) -> None:
        super().setUpClass()
        cls.ev_loop = asyncio.get_event_loop()
        cls.base_asset = "COINALPHA"
        cls.quote_asset = "HBOT"
        cls.trading_pair = f"{cls.base_asset}-{cls.quote_asset}"

    def setUp(self) -> None:
        super().setUp()
        self.mocking_assistant = NetworkMockingAssistant()
        self.throttler = AsyncThrottler(CONSTANTS.RATE_LIMITS)
        self.data_source = KrakenAPIOrderBookDataSource(
            self.throttler, trading_pairs=[self.trading_pair])

    def async_run_with_timeout(self, coroutine: Awaitable, timeout: int = 1):
        ret = self.ev_loop.run_until_complete(
            asyncio.wait_for(coroutine, timeout))
        return ret

    def get_last_traded_prices_mock(self, last_trade_close: Decimal) -> Dict:
        last_traded_prices = {
            "error": [],
            "result": {
                f"X{self.base_asset}{self.quote_asset}": {
                    "a": ["52609.60000", "1", "1.000"],
                    "b": ["52609.50000", "1", "1.000"],
                    "c": [str(last_trade_close), "0.00080000"],
                    "v": ["1920.83610601", "7954.00219674"],
                    "p": ["52389.94668", "54022.90683"],
                    "t": [23329, 80463],
                    "l": ["51513.90000", "51513.90000"],
                    "h": ["53219.90000", "57200.00000"],
                    "o": "52280.40000"
                }
            }
        }
        return last_traded_prices

    def get_depth_mock(self) -> Dict:
        depth = {
            "error": [],
            "result": {
                f"X{self.base_asset}{self.quote_asset}": {
                    "asks": [["52523.00000", "1.199", 1616663113],
                             ["52536.00000", "0.300", 1616663112]],
                    "bids": [["52522.90000", "0.753", 1616663112],
                             ["52522.80000", "0.006", 1616663109]]
                }
            }
        }
        return depth

    def get_public_asset_pair_mock(self) -> Dict:
        asset_pairs = {
            "error": [],
            "result": {
                f"X{self.base_asset}{self.quote_asset}": {
                    "altname": f"{self.base_asset}{self.quote_asset}",
                    "wsname": f"{self.base_asset}/{self.quote_asset}",
                    "aclass_base": "currency",
                    "base": self.base_asset,
                    "aclass_quote": "currency",
                    "quote": self.quote_asset,
                    "lot": "unit",
                    "pair_decimals": 5,
                    "lot_decimals": 8,
                    "lot_multiplier": 1,
                    "leverage_buy": [2, 3, 4, 5],
                    "leverage_sell": [2, 3, 4, 5],
                    "fees": [
                        [0, 0.26],
                        [50000, 0.24],
                    ],
                    "fees_maker": [
                        [0, 0.16],
                        [50000, 0.14],
                    ],
                    "fee_volume_currency": "ZUSD",
                    "margin_call": 80,
                    "margin_stop": 40,
                    "ordermin": "0.005"
                },
            }
        }
        return asset_pairs

    def get_trade_data_mock(self) -> List:
        trade_data = [
            0,
            [["5541.20000", "0.15850568", "1534614057.321597", "s", "l", ""],
             ["6060.00000", "0.02455000", "1534614057.324998", "b", "l", ""]],
            "trade", f"{self.base_asset}/{self.quote_asset}"
        ]
        return trade_data

    @aioresponses()
    def test_get_last_traded_prices(self, mocked_api):
        url = f"{CONSTANTS.BASE_URL}{CONSTANTS.TICKER_PATH_URL}"
        regex_url = re.compile(f"^{url}".replace(".",
                                                 r"\.").replace("?", r"\?"))
        last_traded_price = Decimal("52641.10000")
        resp = self.get_last_traded_prices_mock(
            last_trade_close=last_traded_price)
        mocked_api.get(regex_url, body=json.dumps(resp))

        ret = self.async_run_with_timeout(
            KrakenAPIOrderBookDataSource.get_last_traded_prices(
                trading_pairs=[self.trading_pair], throttler=self.throttler))

        self.assertIn(self.trading_pair, ret)
        self.assertEqual(float(last_traded_price), ret[self.trading_pair])

    @aioresponses()
    def test_get_new_order_book(self, mocked_api):
        url = f"{CONSTANTS.BASE_URL}{CONSTANTS.SNAPSHOT_PATH_URL}"
        regex_url = re.compile(f"^{url}".replace(".",
                                                 r"\.").replace("?", r"\?"))
        resp = self.get_depth_mock()
        mocked_api.get(regex_url, body=json.dumps(resp))

        ret = self.async_run_with_timeout(
            self.data_source.get_new_order_book(self.trading_pair))

        self.assertTrue(isinstance(ret, OrderBook))

        bids_df, asks_df = ret.snapshot
        pair_data = resp["result"][f"X{self.base_asset}{self.quote_asset}"]
        first_bid_price = float(pair_data["bids"][0][0])
        first_ask_price = float(pair_data["asks"][0][0])

        self.assertEqual(first_bid_price, bids_df.iloc[0]["price"])
        self.assertEqual(first_ask_price, asks_df.iloc[0]["price"])

    @aioresponses()
    def test_fetch_trading_pairs(self, mocked_api):
        url = f"{CONSTANTS.BASE_URL}{CONSTANTS.ASSET_PAIRS_PATH_URL}"
        regex_url = re.compile(f"^{url}".replace(".",
                                                 r"\.").replace("?", r"\?"))
        resp = self.get_public_asset_pair_mock()
        mocked_api.get(regex_url, body=json.dumps(resp))

        resp = self.async_run_with_timeout(
            KrakenAPIOrderBookDataSource.fetch_trading_pairs())

        self.assertTrue(len(resp) == 1)
        self.assertIn(self.trading_pair, resp)

    @patch("websockets.connect", new_callable=AsyncMock)
    def test_listen_for_trades(self, ws_connect_mock):
        ws_connect_mock.return_value = self.mocking_assistant.create_websocket_mock(
        )
        resp = self.get_trade_data_mock()
        self.mocking_assistant.add_websocket_text_message(
            websocket_mock=ws_connect_mock.return_value,
            message=json.dumps(resp))
        output_queue = asyncio.Queue()

        self.ev_loop.create_task(
            self.data_source.listen_for_trades(self.ev_loop, output_queue))
        self.mocking_assistant.run_until_all_text_messages_delivered(
            websocket_mock=ws_connect_mock.return_value)

        self.assertTrue(not output_queue.empty())
        msg = output_queue.get_nowait()
        self.assertTrue(isinstance(msg, OrderBookMessage))
        first_trade_price = resp[1][0][0]
        self.assertEqual(msg.content["price"], first_trade_price)

        self.assertTrue(not output_queue.empty())
        msg = output_queue.get_nowait()
        self.assertTrue(isinstance(msg, OrderBookMessage))
        second_trade_price = resp[1][1][0]
        self.assertEqual(msg.content["price"], second_trade_price)
class TestAltmarketsAPIUserStreamDataSource(unittest.TestCase):
    @classmethod
    def setUpClass(cls) -> None:
        super().setUpClass()
        cls.ev_loop = asyncio.get_event_loop()
        cls.base_asset = "COINALPHA"
        cls.quote_asset = "HBOT"
        cls.trading_pair = f"{cls.base_asset}-{cls.quote_asset}"

    def setUp(self) -> None:
        super().setUp()
        self.mocking_assistant = NetworkMockingAssistant()
        altmarkets_auth = AltmarketsAuth(api_key="someKey", secret_key="someSecret")
        self.data_source = AltmarketsAPIUserStreamDataSource(AsyncThrottler(Constants.RATE_LIMITS), altmarkets_auth=altmarkets_auth, trading_pairs=[self.trading_pair])

    def async_run_with_timeout(self, coroutine: Awaitable, timeout: int = 1):
        ret = self.ev_loop.run_until_complete(asyncio.wait_for(coroutine, timeout))
        return ret

    def get_user_trades_mock(self) -> Dict:
        user_trades = {
            "trade": {
                "amount": "1.0",
                "created_at": 1615978645,
                "id": 9618578,
                "market": "rogerbtc",
                "order_id": 2324774,
                "price": "0.00000004",
                "side": "sell",
                "taker_type": "sell",
                "total": "0.00000004"
            }
        }
        return user_trades

    def get_user_orders_mock(self) -> Dict:
        user_orders = {
            "order": {
                "id": 9401,
                "market": "rogerbtc",
                "kind": "ask",
                "side": "sell",
                "ord_type": "limit",
                "price": "0.00000099",
                "avg_price": "0.00000099",
                "state": "wait",
                "origin_volume": "7000.0",
                "remaining_volume": "2810.1",
                "executed_volume": "4189.9",
                "at": 1596481983,
                "created_at": 1596481983,
                "updated_at": 1596553643,
                "trades_count": 272
            }
        }
        return user_orders

    def get_user_balance_mock(self) -> Dict:
        user_balance = {
            "balance": {
                "currency": self.base_asset,
                "balance": "1032951.325075926",
                "locked": "1022943.325075926",
            }
        }
        return user_balance

    @patch("websockets.connect", new_callable=AsyncMock)
    def test_listen_for_user_stream_user_trades(self, ws_connect_mock):
        ws_connect_mock.return_value = self.mocking_assistant.create_websocket_mock()
        output_queue = asyncio.Queue()
        self.ev_loop.create_task(self.data_source.listen_for_user_stream(self.ev_loop, output_queue))

        resp = self.get_user_trades_mock()
        self.mocking_assistant.add_websocket_text_message(
            websocket_mock=ws_connect_mock.return_value,
            message=json.dumps(resp))
        ret = self.async_run_with_timeout(coroutine=output_queue.get())
        self.assertEqual(ret, resp)

        resp = self.get_user_orders_mock()
        self.mocking_assistant.add_websocket_text_message(
            websocket_mock=ws_connect_mock.return_value,
            message=json.dumps(resp))
        ret = self.async_run_with_timeout(coroutine=output_queue.get())

        self.assertEqual(ret, resp)

        resp = self.get_user_balance_mock()
        self.mocking_assistant.add_websocket_text_message(
            websocket_mock=ws_connect_mock.return_value,
            message=json.dumps(resp))
        ret = self.async_run_with_timeout(coroutine=output_queue.get())

        self.assertEqual(ret, resp)

    @patch("websockets.connect", new_callable=AsyncMock)
    def test_listen_for_user_stream_skips_subscribe_unsubscribe_messages_updates_last_recv_time(self, ws_connect_mock):
        ws_connect_mock.return_value = self.mocking_assistant.create_websocket_mock()
        resp = {
            "success": {
                "message": "subscribed",
                "time": 1632223851,
                "streams": "trade"
            }
        }
        self.mocking_assistant.add_websocket_text_message(
            websocket_mock=ws_connect_mock.return_value,
            message=json.dumps(resp))
        resp = {
            "success": {
                "message": "unsubscribed",
                "time": 1632223851,
                "streams": "trade"
            }
        }
        self.mocking_assistant.add_websocket_text_message(
            websocket_mock=ws_connect_mock.return_value,
            message=json.dumps(resp))

        output_queue = asyncio.Queue()
        self.ev_loop.create_task(self.data_source.listen_for_user_stream(self.ev_loop, output_queue))
        self.mocking_assistant.run_until_all_text_messages_delivered(ws_connect_mock.return_value)

        self.assertTrue(output_queue.empty())
        np.testing.assert_allclose([time.time()], self.data_source.last_recv_time, rtol=1)
class TestKucoinAPIUserStreamDataSource(unittest.TestCase):
    @classmethod
    def setUpClass(cls) -> None:
        super().setUpClass()
        cls.ev_loop = asyncio.get_event_loop()
        cls.base_asset = "COINALPHA"
        cls.quote_asset = "HBOT"
        cls.trading_pair = f"{cls.base_asset}-{cls.quote_asset}"
        cls.api_key = "someKey"
        cls.api_passphrase = "somePassPhrase"
        cls.api_secret_key = "someSecretKey"

    def setUp(self) -> None:
        super().setUp()
        self.throttler = AsyncThrottler(CONSTANTS.RATE_LIMITS)
        self.auth = KucoinAuth(self.api_key, self.api_passphrase,
                               self.api_secret_key)
        self.data_source = KucoinAPIUserStreamDataSource(
            self.throttler, self.auth)
        self.mocking_assistant = NetworkMockingAssistant()

    def async_run_with_timeout(self, coroutine: Awaitable, timeout: int = 1):
        ret = self.ev_loop.run_until_complete(
            asyncio.wait_for(coroutine, timeout))
        return ret

    @staticmethod
    def get_listen_key_mock():
        listen_key = {
            "code": "200000",
            "data": {
                "token":
                "someToken",
                "instanceServers": [{
                    "endpoint": "wss://someEndpoint",
                    "encrypt": True,
                    "protocol": "websocket",
                    "pingInterval": 18000,
                    "pingTimeout": 10000,
                }]
            }
        }
        return listen_key

    @aioresponses()
    def test_get_listen_key_raises(self, mock_api):
        url = CONSTANTS.BASE_PATH_URL + CONSTANTS.PRIVATE_WS_DATA_PATH_URL
        mock_api.post(url, status=500)

        with self.assertRaises(IOError):
            self.async_run_with_timeout(self.data_source.get_listen_key())

    @aioresponses()
    def test_get_listen_key(self, mock_api):
        url = CONSTANTS.BASE_PATH_URL + CONSTANTS.PRIVATE_WS_DATA_PATH_URL
        resp = self.get_listen_key_mock()
        mock_api.post(url, body=json.dumps(resp))

        ret = self.async_run_with_timeout(self.data_source.get_listen_key())

        self.assertEqual(ret, resp)  # shallow comparison ok

    @aioresponses()
    @patch("websockets.connect", new_callable=AsyncMock)
    def test_listen_to_user_stream(self, mock_api, ws_connect_mock):
        url = CONSTANTS.BASE_PATH_URL + CONSTANTS.PRIVATE_WS_DATA_PATH_URL
        resp = self.get_listen_key_mock()
        mock_api.post(url, body=json.dumps(resp))

        ws_connect_mock.return_value = self.mocking_assistant.create_websocket_mock(
        )
        msg = "someMsg"
        msg_queue = asyncio.Queue()
        self.mocking_assistant.add_websocket_text_message(
            ws_connect_mock.return_value, json.dumps(msg))

        self.ev_loop.create_task(
            self.data_source.listen_for_user_stream(self.ev_loop, msg_queue))
        self.mocking_assistant.run_until_all_text_messages_delivered(
            ws_connect_mock.return_value)

        self.assertTrue(not msg_queue.empty())

        queued = msg_queue.get_nowait()

        self.assertEqual(msg, queued)

    @aioresponses()
    @patch("websockets.connect", new_callable=AsyncMock)
    def test_listen_for_user_stream_closes_ws_on_exception(
            self, mock_api, ws_connect_mock):
        url = CONSTANTS.BASE_PATH_URL + CONSTANTS.PRIVATE_WS_DATA_PATH_URL
        resp = self.get_listen_key_mock()
        mock_api.post(url, body=json.dumps(resp))
        raised_event = asyncio.Event()

        async def raise_exception():
            raised_event.set()
            raise IOError

        ws_connect_mock.return_value = self.mocking_assistant.create_websocket_mock(
        )
        ws_connect_mock.return_value.recv.side_effect = raise_exception

        self.ev_loop.create_task(
            self.data_source.listen_for_user_stream(self.ev_loop,
                                                    asyncio.Queue()))
        self.async_run_with_timeout(coroutine=raised_event.wait())

        ws_connect_mock.return_value.close.assert_called()