unittest测试Flask API根路径返回404错误如何解决
问题原因
路由注册逻辑写在Main类的__init__构造方法中,两种运行场景的执行逻辑差异导致了问题:
- 直接启动
main.py时,代码会进入if __name__ == "__main__"分支,执行main = Main()实例化对象,构造方法自动运行,/路径的路由才会被注册到Flask app实例上,因此直接访问服务可以得到正常响应。 - 运行单元测试时,仅导入了
Main类,直接通过类属性Main.app生成测试客户端,全程没有实例化Main对象,构造方法内的路由注册逻辑完全没有执行,Flask app中不存在/对应的路由规则,请求自然返回404状态码。
注:测试输出里Expected :404 Actual :200是unittest断言的参数顺序显示问题,不影响问题定位。
修复方案
二选一即可:
方案1:最小改动,测试时先实例化Main触发路由注册
只需要修改测试文件test_main.py的setUp方法,在生成测试客户端前先实例化Main对象,触发构造方法完成路由注册:
def setUp(self): # 实例化Main,执行__init__中的路由注册逻辑 Main() self.ctx = Main.app.app_context() self.ctx.push() self.client = Main.app.test_client()
因为app是Main的类属性,所有实例共享同一个app对象,实例化操作就会完成路由绑定,改完再跑测试就能拿到200状态码。
方案2(推荐):调整代码结构,避免路由注册依赖类实例化
Flask不推荐把路由注册逻辑塞到类构造方法中,这种写法很容易出现漏实例化导致路由丢失的问题。更清晰的写法是把app初始化、路由注册逻辑独立出来,参考调整后的main.py:
from flask import Flask # 独立初始化app实例 app = Flask(__name__) # 直接注册路由,不依赖类实例化 @app.route('/', methods=['GET']) def index(): return "Hello - welcome to my API" class Main: def __init__(self): # 其他业务初始化逻辑放在这里 pass if __name__ == "__main__": app.run(debug=True, host="0.0.0.0", port=5003)
对应调整测试代码,直接导入独立的app实例生成测试客户端即可,不需要依赖Main类的实例化:
import unittest # 直接导入初始化好的app实例 from src.main import app class MainTest(unittest.TestCase): def setUp(self): self.ctx = app.app_context() self.ctx.push() self.client = app.test_client() def tearDown(self): self.ctx.pop() def test_index(self): """ Test index page of the flask API """ response = self.client.get("/") self.assertEqual(response.status_code, 200) if __name__ == "__main__": unittest.main()
内容的提问来源于stack exchange,提问作者Europa
相关产品推荐
相关产品推荐

