Pytest测试Flask应用:相同用例首次通过第二次路由报404如何解决
问题原因
核心是路由导入的执行时机不符合预期:
你将from app import routes, models写在了client fixture内部,而Python的模块导入是全局唯一的,首次执行后不会重复运行:
- 第一个测试用例触发fixture执行时,会创建新的Flask实例,随后导入routes模块,路由规则正常注册到该实例上,因此访问
/login能得到正确响应。 - 第二个测试用例触发fixture执行时,会创建一个全新的Flask实例,但此时routes模块已经完成导入,导入语句不会重复执行,新的实例没有注册任何路由,因此访问
/login返回404。
解决方案
方案1(推荐):调整应用工厂写法
按照Flask应用工厂的标准实践,将路由、蓝图、扩展的初始化逻辑全部放到create_app函数内部,示例如下:
# app/__init__.py 中的create_app修改 def create_app(config=None): app = Flask(__name__) # 加载配置 if config: app.config.from_object(config) # 初始化扩展 db.init_app(app) # 注册路由/蓝图 from . import routes, models # 其余初始化逻辑 return app
修改完成后,删除client fixture内的from app import routes, models代码即可。
方案2:调整fixture作用域
如果暂时不想调整应用结构,可以将client fixture的作用域改为模块级,让所有测试共用同一个Flask实例和客户端:
# 修改fixture定义,增加scope参数 @pytest.fixture(scope="module") def client(): testConfig = TestConfig() app = create_app(testConfig) from app import routes, models with app.test_client() as client: with app.app_context(): db.create_all() yield client
注意该方案下所有测试共用同一个内存数据库,需要自行处理测试用例之间的数据隔离问题。
内容的提问来源于stack exchange,提问作者newbie
相关产品推荐
相关产品推荐

