Search code examples
pythonwebsockettornado

close method of Tornado's WebsocketClientConnection doesn't invoke on_close method of Websocket Handler


I have a WebsocketHandler like this:

class MyHandler(WebSocketHandler):

    def open(self, *args, **kwargs):
        self.application.logger.info('WebSocket connection opened from %s', self.request.remote_ip)

    def on_close(self):
        self.application.logger.info('WebSocket connection closed')

    def on_message(self, message):
        self.write_message(message)

and I have some tests using pytest like this:

@pytest.fixture
def app(request):
    request.cls.app_fixture = create_app(TornadoConfig)


@pytest.mark.usefixtures("app")
class TestWebSocket(testing.AsyncHTTPTestCase):

    def get_app(self):
        return self.app_fixture

    def setUp(self):
        super(TestWebSocket, self).setUp()
        server = httpserver.HTTPServer(self.app_fixture)
        self.socket, self.port = testing.bind_unused_port()
        server.add_socket(self.socket)

    def _mk_client(self):
        client = websocket_connect('ws://localhost:{}/ws/'.format(self.port))
        TestWebSocket.clients.append(client)
        return client

    @testing.gen_test
    def test_auto_complete(self):
       client = yield self._mk_client()
       client.write_message('test')
       response = yield client.read_message()

       assert response == 'test'

       client.close()

although I traced it and I'm sure that close method is called, but client.close() doesn't have any effect on MyHandler and on_close is never called!


Solution

  • I used ThreadPoolExecutor to solve my problem so I created a thread_pool:

    thread_pool = ThreadPoolExecutor(1)
    

    and wrote another method to close the client's connection:

    def close_ws(self, client):
        client.close()
        time.sleep(1)
        self.close_future.set_result('done')
    

    and at the end of my test method I did:

    self.thread_pool.submit(self.close_ws, client)
    yield self.close_future