You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何不使用已弃用类测试tornado.web.RequestHandler子类

Tornado 6.2+ 测试RequestHandler的正确方式

问题1:实例化RequestHandler时的supports_http_1_1错误

你用错了请求对象!tornado.web.RequestHandler需要的是服务端请求对象tornado.httputil.HTTPServerRequest,而不是客户端用的tornado.httpclient.HTTPRequest——这俩是完全不同的类,后者没有supports_http_1_1属性,所以才会报错。

正确的实例化代码示例:

import tornado.web
import tornado.httputil

# 自定义你的RequestHandler子类
class MyHandler(tornado.web.RequestHandler):
    async def post(self):
        self.write({"status": "ok"})

# 创建Application实例
app = tornado.web.Application([(r"/", MyHandler)])

# 构造服务端请求对象
request = tornado.httputil.HTTPServerRequest(
    method="POST",
    uri="/",
    headers=tornado.httputil.HTTPHeaders(),
    body=None
)

# 实例化Handler
handler = MyHandler(app, request)
# 现在可以调用handler的方法测试了,比如手动触发post方法
import asyncio
asyncio.run(handler.post())
print(handler._write_buffer)  # 查看输出内容

问题2:使用unittest.IsolatedAsyncioTestCase的原因和方法

为什么要用它?

Tornado 6.2弃用了旧的AsyncTestCase系列,官方推荐用Python标准库的unittest.IsolatedAsyncioTestCase,核心原因是:

  • 它是Python官方提供的异步测试工具,不需要依赖Tornado自己的事件循环管理逻辑
  • 支持直接写async def的测试方法,自动处理事件循环的创建和销毁,避免循环复用的问题

具体用法示例

下面是一个完整的测试用例,测试自定义Handler的异步方法:

import unittest
import tornado.web
import tornado.httputil

class MyHandler(tornado.web.RequestHandler):
    async def get(self):
        name = self.get_query_argument("name", default="guest")
        self.write({"message": f"Hello, {name}!"})

class TestMyHandler(unittest.IsolatedAsyncioTestCase):
    async def test_get_handler(self):
        # 创建Application和请求对象
        app = tornado.web.Application([(r"/", MyHandler)])
        # 构造带查询参数的请求
        request = tornado.httputil.HTTPServerRequest(
            method="GET",
            uri="/?name=Alice",
            headers=tornado.httputil.HTTPHeaders(),
        )
        # 实例化Handler
        handler = MyHandler(app, request)
        
        # 执行get方法
        await handler.get()
        
        # 断言输出结果
        self.assertEqual(handler._write_buffer[0].decode(), '{"message": "Hello, Alice!"}')

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

如果要测试HTTP接口的完整流程(模拟请求整个应用),可以结合tornado.testing.AsyncHTTPClient在IsolatedAsyncioTestCase里使用:

import unittest
import tornado.web
from tornado.httpclient import AsyncHTTPClient

class MyHandler(tornado.web.RequestHandler):
    async def post(self):
        data = self.get_body_argument("data")
        self.set_status(200)
        self.write({"received": data})

class TestMyHandlerHTTP(unittest.IsolatedAsyncioTestCase):
    async def test_http_post(self):
        app = tornado.web.Application([(r"/", MyHandler)])
        # 监听一个随机端口
        app.listen(8888)
        client = AsyncHTTPClient()
        
        # 发送POST请求
        response = await client.fetch(
            "http://localhost:8888/",
            method="POST",
            body="data=test_content"
        )
        
        # 断言响应
        self.assertEqual(response.code, 200)
        self.assertEqual(response.body.decode(), '{"received": "test_content"}')

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

内容的提问来源于stack exchange,提问作者AmagicalFishy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 02:45:07