我正在开发一个Flask应用程序,并使用Flask安全性进行用户身份验证(这反过来又使用下面的Flask登录)。
我有一个需要身份验证的路由,/user
。我正在尝试编写一个单元测试,它测试经过身份验证的用户,这将返回适当的响应。
在unittest中,我创建一个用户,并按照该用户的喜好进行日志记录:
from unittest import TestCase
from app import app, db
from models import User
from flask_security.utils import login_user
class UserTest(TestCase):
def setUp(self):
self.app = app
self.client = self.app.test_client()
self._ctx = self.app.test_request_context()
self._ctx.push()
db.create_all()
def tearDown(self):
if self._ctx is not None:
self._ctx.pop()
db.session.remove()
db.drop_all()
def test_user_authentication():
# (the test case is within a test request context)
user = User(active=True)
db.session.add(user)
db.session.commit()
login_user(user)
# current_user here is the user
print(current_user)
# current_user within this request is an anonymous user
r = test_client.get('/user')
在测试中current_user
返回正确的用户。但是,请求的视图总是返回一个AnonymousUser
作为current_user
。
/user
路由定义为:
class CurrentUser(Resource):
def get(self):
return current_user # returns an AnonymousUser
我很确定我只是没有完全理解测试烧瓶请求上下文是如何工作的。我已经阅读了这本烧瓶Request Context documentation一堆,但仍然不理解如何进行这个特定的单元测试。
我不太喜欢显示的其他解决方案,主要是因为您必须将密码保存在一个单元测试文件中(我使用的是Flask LDAP登录,所以添加一个虚拟用户是不明显的,等等),所以我绕过了它:
在我设置测试应用程序的地方,我添加了:
但是,我对flask应用程序的测试实例做了很多更改,比如使用不同的DB,在这里构造它,所以添加路由并不会使代码明显混乱。Obv实际应用程序中不存在此路由。
然后我会:
之后使用
test_client
执行的任何操作都应登录。问题是
test_client.get()
调用会导致推送一个新的请求上下文,因此您在测试用例的setUp()
方法中推送的上下文不是/user
处理程序看到的上下文。我认为文档的Logging In and Out和Test Adding Messages部分中显示的方法是测试登录的最佳方法。其思想是通过应用程序发送登录请求,就像普通客户机那样。这将负责在测试客户端的用户会话中注册已登录的用户。
问题在于不同的请求上下文。
在普通的Flask应用程序中,每个请求都会创建一个新的上下文,该上下文将在整个链中重用,直到创建最终响应并将其发送回浏览器。
当您创建并运行烧瓶测试并执行请求(例如
self.client.post(...)
)时,在接收到响应后将丢弃上下文。因此,current_user
始终是AnonymousUser
。为了解决这个问题,我们必须告诉Flask在整个测试中重用相同的上下文。只需将代码包装为:
您可以在以下精彩文章中阅读更多关于此主题的内容: https://realpython.com/blog/python/python-web-applications-with-flask-part-iii/
示例
之前:
之后:
相关问题 更多 >
编程相关推荐