【问题标题】:Using python mocking library on sqlalchemy在 sqlalchemy 上使用 python 模拟库
【发布时间】:2016-05-28 10:25:18
【问题描述】:

我正在使用 sqlalchemy 来查询我的数据库中的一个项目。并排,我是单元测试的新手,我正在尝试学习如何进行单元测试来测试我的数据库。我尝试使用模拟库进行测试,但到目前为止,这似乎非常困难。

所以我编写了一段代码来创建一个Session 对象。该对象用于连接数据库。

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.exc import OperationalError, ArgumentError

test_db_string = 'postgresql+psycopg2://testdb:hello@localhost/' \
                   'test_databasetable'
def get_session(database_connection_string):
    try:
        Base = declarative_base()
        engine = create_engine(database_connection_string)
        Base.metadata.bind = engine
        DBSession = sessionmaker(bind=engine)
        session = DBSession()
        connection = session.connection()
        return session
    except OperationalError:
        return None
    except ArgumentError:
        return None

所以我为这个函数做了一个单元测试用例:

import mock
import unittest
from mock import sentinel
import get_session

class TestUtilMock(unittest.TestCase):

    @mock.patch('app.Utilities.util.create_engine')  # mention the whole path
    @mock.patch('app.Utilities.util.sessionmaker')
    @mock.patch('app.Utilities.util.declarative_base')
    def test_get_session1(self, mock_delarative_base, mock_sessionmaker,
                         mock_create_engine):
        mock_create_engine.return_value = sentinel.engine
        get_session('any_path')
        mock_delarative_base.called
        mock_create_engine.assert_called_once_with('any_path')
        mock_sessionmaker.assert_called_once_with(bind=sentinel.engine)

正如您在我的单元测试中看到的,我无法从session = DBSession() 行开始测试get_session() 中的代码。到目前为止,在谷歌搜索之后,我无法确定返回的模拟值是否也可以用于模拟函数调用 - 例如,我模拟 session 对象并验证我是否调用了 session.connection()

上面写单元测试用例的方法对吗?有没有更好的方法来做到这一点?

【问题讨论】:

    标签: python unit-testing sqlalchemy mocking python-mock


    【解决方案1】:

    首先你也可以通过测试session = DBSession()

    self.assertEqual(get_session('any_path'), mock_sessionmaker.return_value.return_value)
    

    此外,mock_delarative_base.called 不是断言,不能失败。替换为

    self.assertTrue(mock_delarative_base.called)
    

    一般注意事项

    编写这样的测试可能非常耗时,并且会使您的生产代码真正与测试代码耦合。最好编写自己的包装器,为您的业务代码提供一个舒适的接口,并使用一些模拟和真实(简单)测试对其进行测试:您应该信任sqlalchemy 实现并测试您的包装器如何调用它

    在您可以通过一个您可以控制的假对象来模拟您的包装器之后,或者使用模拟并检查您的代码如何调用它,但您的包装器将只显示一些业务接口并且模拟它应该非常简单。

    【讨论】:

    • 感谢您的意见。我只是想知道如何模拟上面示例中的自定义对象。由于某些函数依赖于其他函数,我想使用模拟来断言这些函数是用正确的参数调用的。非常感谢您的帮助。
    猜你喜欢
    • 2018-11-10
    • 1970-01-01
    • 2016-07-28
    • 2011-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-25
    相关资源
    最近更新 更多