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检查更新,它应该提供您正在寻找的内容,您还应该为异常分支添加一个测试