使用Websockets进行Tornado单元测试 - 栈上下文有何影响?

3

我已经使用Tornado服务器有一段时间了,我必须说我很喜欢它。 我有一个运行在Python 3.2上的Tornado服务器,处理web socket和HTTP请求。 我想编写一些单元测试(使用web sockets)并使用ws2py(实现一个ws客户端来与Tornado IOLoop一起使用)。我发现Tornado有AsyncTestCase类,特别是在与AsyncHTTPClient一起使用时,看起来非常有趣,正如其文档所述:

class MyTestCase2(AsyncTestCase):
    def test_http_fetch(self):
        client = AsyncHTTPClient(self.io_loop)
        client.fetch("http://www.tornadoweb.org/", self.stop)
        response = self.wait()
        # Test contents of response
        self.assertIn("FriendFeed", response.body)

我想使用AsyncTestCase处理Websockets, 客户端没有问题,我可以发送和接收消息。
我猜我需要将self.stop作为回调传递给客户端,以便通过调用wait()来检索接收到的消息,就像上面的示例一样。但不知何故,这行不通,这是我的代码:
class SQLRequests(AsyncTestCase):
    """Tests sql requests"""

    def test_sql_req_1(self):
        """first test function"""
        client = AsyncWSClient(httpBaseUrl, self.io_loop)
        client.sendMessage('some_message', self.stop)

        response = self.wait()
        if response.data:
            print('got %s' % str(response.data))
            # some test
            self.assertTrue(True)


if __name__ == '__main__':
    unittest.main()

这是我的 WebSocket 客户端:

class AsyncWSClient(TornadoWebSocketClient):
"""
Asynchronous web socket client based on ws4py's tornadoclient
Sends a message and calls callback with received message
"""
def __init__(self, url, ioLoop=None, **kwargs):
    TornadoWebSocketClient.__init__(self, url, io_loop=ioLoop, **kwargs)
    self._callback = None
    self._message = None

def opened(self):
    """called when web socket opened"""
    self.send(self._message, binary=False)      

def received_message(self, message):
    """Received a message"""
            self.close()
    if self._callback:
        self._callback(message)

def sendMessage(self, message, callback):
    """Connects and sends message when connected"""
    self._message = message
    self._callback = callback
    self.connect()

我确实收到了一个名为ws2py.messaging.TextMessage的对象作为响应,但它的数据字段是None,尽管客户端已经接收到了一些数据。如果我查看AsyncTestCase,在调用回调函数之前,该对象中有一些数据,但当它作为wait()的返回值传递时,数据不知何故消失了。
我注意到在tornado中有一个神秘的东西叫做stack_context,这是否与我的问题有关?
1个回答

4
问题在于消息“data”包含在messagedata属性中。一旦调用了received_messagemessage.data将被重置为None(https://github.com/Lawouach/WebSocket-for-Python/blob/master/ws4py/websocket.py#L369)。
因此,只需传递message.data而不是完整的message来调用你的回调函数。像这样:
def received_message(self, message):
    """Received a message"""
    self.close()
    if self._callback:
       self._callback(message.data)

它有效了,非常感谢!我不记得我当时正在做什么,但是它打印出了信息。 - Pedru

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接