python模拟sqlalchemy连接
我有一个简单的函数,可以连接到数据库并获取一些数据python模拟sqlalchemy连接,python,sqlalchemy,mocking,python-mock,Python,Sqlalchemy,Mocking,Python Mock,我有一个简单的函数,可以连接到数据库并获取一些数据 db.py from sqlalchemy import create_engine from sqlalchemy.pool import NullPool def _create_engine(app): impac_engine = create_engine( app['DB'], poolclass=NullPool # this setting enables NOT to use P
db.py
from sqlalchemy import create_engine
from sqlalchemy.pool import NullPool
def _create_engine(app):
impac_engine = create_engine(
app['DB'],
poolclass=NullPool # this setting enables NOT to use Pooling, preventing from timeout issues.
)
return impac_engine
def get_all_pos(app):
engine = _create_engine(app)
qry = """SELECT DISTINCT id, name FROM p_t ORDER BY name ASC"""
try:
cursor = engine.execute(qry)
rows = cursor.fetchall()
return rows
except Exception as re:
raise re
我试图通过模拟这种连接来编写一些测试用例-
tests.py
import unittest
from db import get_all_pos
from unittest.mock import patch
from unittest.mock import Mock
class TestPosition(unittest.TestCase):
@patch('db.sqlalchemy')
def test_get_all_pos(self, mock_sqlalchemy):
mock_sqlalchemy.create_engine = Mock()
get_all_pos({'DB': 'test'})
if __name__ == '__main__':
unittest.main()
当我运行上述文件python tests.py时,出现以下错误-
"Could not parse rfc1738 URL from string '%s'" % name
sqlalchemy.exc.ArgumentError: Could not parse rfc1738 URL from string 'test'
不应该mock_sqlalchemy.create_engine=mock()给我一个mock对象并绕过URL检查
另一个选项是模拟您的
\u create\u引擎
功能。因为这是一个单元测试,我们想要测试get\u all\u pos
,所以我们不需要依赖\u create\u engine
的行为,所以我们可以这样修补它
import unittest
import db
from unittest.mock import patch
class TestPosition(unittest.TestCase):
@patch.object(db, '_create_engine')
def test_get_all_pos(self, mock_sqlalchemy):
args = {'DB': 'test'}
db.get_all_pos(args)
mock_sqlalchemy.assert_called_once()
mock_sqlalchemy.assert_called_with({'DB': 'test'})
if __name__ == '__main__':
unittest.main()
如果要测试某些结果,需要正确设置所有相应的属性。我建议不要将它链接到一个调用中,这样它就更具可读性,如下所示
import unittest
import db
from unittest.mock import patch
from unittest.mock import Mock
class Cursor:
def __init__(self, vals):
self.vals = vals
def fetchall(self):
return self.vals
class TestPosition(unittest.TestCase):
@patch.object(db, '_create_engine')
def test_get_all_pos(self, mock_sqlalchemy):
to_test = [1, 2, 3]
mock_cursor = Mock()
cursor_attrs = {'fetchall.return_value': to_test}
mock_cursor.configure_mock(**cursor_attrs)
mock_execute = Mock()
engine_attrs = {'execute.return_value': mock_cursor}
mock_execute.configure_mock(**engine_attrs)
mock_sqlalchemy.return_value = mock_execute
args = {'DB': 'test'}
rows = db.get_all_pos(args)
mock_sqlalchemy.assert_called_once()
mock_sqlalchemy.assert_called_with({'DB': 'test'})
self.assertEqual(to_test, rows)
你能详细说明一下想要的断言是什么吗?测试当前没有断言。您还需要模拟
sqlalchemy
中的特定模块,而不是整个库本身,因此您的问题似乎有两个方面。这应该是我的断言-模拟请求。创建\u引擎。游标。获取\u全部。断言调用\u once()…我应该模拟sqlalchemy对象,然后分别模拟每个方法吗;mock_sqlalchemy.create_engine.return_value=mock_engineeyes您必须创建对象,这些对象实现您的引擎执行的方法。您的函数不使用db.sql_alchemy.create_engine
;它使用db.create_引擎
;这就是你需要模拟的。没问题,但是这个测试并没有真正测试get_all\u pos
的结果,所以我建议实现execute
和fetchall
的行为,这样你就可以检查你的两个逻辑分支(try/except
)@user1050619检查更新,它应该提供您正在寻找的内容,您还应该为异常分支添加一个测试