Set*_*ian 6 python sqlalchemy flask python-unittest
我的目标是能够使用 Flask 应用程序 test_client 测试路由self.client.post(url, ...
。我遇到的问题是,每当我使用它发出请求时,我都会遇到来自 SQLAlchemy 的 DetachedInstanceError,说刷新或延迟加载操作都不会发生。
这是我的设置:
class BaseTestCase(unittest.TestCase):
def setUp(self):
self.postgresql = Postgresql()
config = {
'FLASK_ENV': 'test',
'SQLALCHEMY_DATABASE_URI': self.postgresql.url()
}
with patch.dict('os.environ', config):
self.app = create_app()
self.client = self.app.test_client()
ctx = self.app.app_context()
ctx.push()
db.create_all()
self.assertEqual(app.testing, True)
reset_fake_data()
def tearDown(self):
db.session.remove()
self.postgresql.stop()
def post(self, url, data={}, headers={}):
headers = {'Content-Type': 'application/json', **headers}
return self.client.post(url, headers=headers, data=json.dumps(data))
def post_with_auth_token(self, url, data={}, headers={}):
headers = {'Authorization': f'Bearer {self.auth_token}'}
return self.post(url, headers=headers, data=data)
Run Code Online (Sandbox Code Playgroud)
然后在另一个文件中,我调用它response = self.post('/api/users/register', data=data)
并得到错误:
sqlalchemy.orm.exc.DetachedInstanceError: Parent instance <User at 0x10ea43f98> is not bound to a Session; lazy load operation of attribute 'courses' cannot proceed (Background on this error at: http://sqlalche.me/e/bhk3)
Run Code Online (Sandbox Code Playgroud)
下面是路线。我创建了一个用户对象,然后尝试向其中添加课程,但显然,当我尝试这样做时user.courses.append
,它无法延迟加载课程。我已经研究过禁用该expire_on_commit
属性,但我不确定如何仅在测试情况下执行此操作,或者是否有更好的方法来解决此问题。
我读到从懒加载到急切加载也可以解决它,但我宁愿保持延迟加载,而且当我将关系设置为lazy='subquery'
无论如何时它似乎没有修复它。
class BaseTestCase(unittest.TestCase):
def setUp(self):
self.postgresql = Postgresql()
config = {
'FLASK_ENV': 'test',
'SQLALCHEMY_DATABASE_URI': self.postgresql.url()
}
with patch.dict('os.environ', config):
self.app = create_app()
self.client = self.app.test_client()
ctx = self.app.app_context()
ctx.push()
db.create_all()
self.assertEqual(app.testing, True)
reset_fake_data()
def tearDown(self):
db.session.remove()
self.postgresql.stop()
def post(self, url, data={}, headers={}):
headers = {'Content-Type': 'application/json', **headers}
return self.client.post(url, headers=headers, data=json.dumps(data))
def post_with_auth_token(self, url, data={}, headers={}):
headers = {'Authorization': f'Bearer {self.auth_token}'}
return self.post(url, headers=headers, data=data)
Run Code Online (Sandbox Code Playgroud)
尝试这样的事情
class BaseTestCase(unittest.TestCase):
@classmethod
def setUpClass(cls):
self.postgresql = Postgresql()
config = {
'FLASK_ENV': 'test',
'SQLALCHEMY_DATABASE_URI': self.postgresql.url()
}
with patch.dict('os.environ', config):
self.app = create_app()
self.client = self.app.test_client()
self.app.app_context().push()
def setUp(self):
with self.app.app_context():
db.create_all()
self.assertEqual(app.testing, True)
reset_fake_data()
def tearDown(self):
with self.app.app_context():
db.session.remove()
self.postgresql.stop()
def post(self, url, data={}, headers={}):
headers = {'Content-Type': 'application/json', **headers}
return self.client.post(url, headers=headers, data=json.dumps(data))
def post_with_auth_token(self, url, data={}, headers={}):
headers = {'Authorization': f'Bearer {self.auth_token}'}
return self.post(url, headers=headers, data=data)
Run Code Online (Sandbox Code Playgroud)