Python单元测试中模拟数据库连接/未知类型

时间:2017-01-10 22:18:22

标签: python unit-testing mocking magicmock

这里是蟒蛇新手。 我的类使用数据库连接来包装一些函数。我已经成功找到了一些基本的例子。对于我正在使用的更复杂的库,我找不到模拟数据库连接的近似示例。在我的,

class DBSAccess():
    def __init__(self, db_con):
        self.db_con = db_con

    def get_db_perm(self, target_user):
      ## this is where I start having trouble
        with self.db_con.cursor() as cursor:
            cursor.execute("SELECT CAST(sum(maxperm) AS bigint) \
            FROM dbc.diskspace \
            WHERE  databasename = '%s' \
            GROUP BY databasename" % (target_user))

            res = cursor.fetchone()
            if res is not None:
                return res[0]
            else:
                msg = target_user + " does not exist"
                return msg

其中db_con是teradata.UdaExec返回连接

udaExec = teradata.UdaExec (appName="whatever", version="1.0", logConsole=True)
db_con = udaExec.connect(method="odbc", system='my_sys', username='my_name', password='my_pswd')
dbc_instance = tdtestpy.DBSaccess (db_con)

因此,为了我的测试不使用任何真正的连接,我必须嘲笑一些事情。我试过这个组合:

class DBAccessTest(unittest.TestCase):
  def test_get_db_free_perm_expects_500(self):
    uda_exec = mock.Mock(spec=teradata.UdaExec)
    db_con = MagicMock(return_value=None)
    db_con.cursor.fetchone.return_value = [500]
    uda_exec.connect.return_value = db_con
    self.dbc_instance = DBSAccess(db_con)
    self.assertEqual(self.dbc_instance.get_db_free_perm("dbc"), 500)

但我的结果搞砸了,因为fetchone正在返回一个模拟,而不是我预期的[500]一个项目列表:

AssertionError: <MagicMock name='mock.connect().cursor().[54 chars]312'> != 500

我已经找到了一些例子,其中有一个&#39; with block&#39;用于测试OS操作,但与数据库无关。另外,我不知道db_con.cursor是什么数据类型,因此我无法准确地说明这一点 - 我认为光标位于Teradata/PyTd的UdaExecConnection.cursor()中。

我需要知道如何模拟响应,这将允许我在我的方法中测试逻辑。

1 个答案:

答案 0 :(得分:10)

您的问题来源如下:

with self.db_con.cursor() as cursor:

with行调用__enter__ method,在您的情况下生成一个新模拟。

解决方案是mock __enter__ method

db_con.cursor.return_value.__enter__.return_value = cursor

您的测试:

class DBAccessTest(unittest.TestCase):
    def test_get_db_free_perm_expects_500(self):
        db_con = MagicMock(UdaExecConnection)
        cursor = MagicMock(UdaExecCursor)
        cursor.fetchone.return_value = [500]
        db_con.cursor.return_value.__enter__.return_value = cursor
        self.dbc_instance = DBSAccess(db_con)
        self.assertEqual(self.dbc_instance.get_db_perm("dbc"), 500)

    def test_get_db_free_perm_expects_None(self):
        db_con = MagicMock(UdaExecConnection)
        cursor = MagicMock(UdaExecCursor)
        cursor.fetchone.return_value = None
        db_con.cursor.return_value.__enter__.return_value = cursor
        self.dbc_instance = DBSAccess(db_con)
        self.assertEqual(self.dbc_instance.get_db_perm("dbc"), "dbc does not exist")