来自基类的 Python 模拟 psycopg2

标签 python mocking psycopg2

您好,我在从继承类模拟光标对象时遇到了麻烦。 这是我的代码的一部分:

# classa.py
class ClassA(ClassB):
    def __init__(self, params):
        ClassB.__init__(params)
        # other params

    def get_current_attr(self):
        sql = "SELECT max(attr) FROM {};".format(self.table_name)
        self.rs_cursor.execute(sql)
        current_attr = self.rs_cursor.fetchone()[0]
        return current_attr

# classb.py
import psycopg2

class ClassB:
    def __init__(self, params):
        self.redshift_conn = self.open_redshift_connection()
        self.redshift_conn.set_isolation_level(
            psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
        self.rs_cursor = self.redshift_conn.cursor()

现在我想在 ClassA 的 get_current_attr() 函数中模拟 psycopg2 光标。我尝试这样做:

@mock.patch("mypackage.classa.classb.psycopg2.connect")
def test_get_current_attr(self, mock_connect):
    mock_con = mock_connect.return_value
    mock_cur = mock_con.cursor.return_value
    mock_cur.fetch_one.return_value = 1
    result = self.gap_load_instance.get_current_batch_id()
    mock_cur.execute.assert_called_with(
        "SELECT max(attr) FROM tablename"
    )

我得到:

raise AssertionError('Expected call: %s\nNot called' % (expected,))

谁能帮我解决这个问题吗?

最佳答案

模拟整个 psycopg2 是最简单的。我已经为您缺少的函数添加了 stub ,但类似这样的东西应该可以工作:

# classa.py
class ClassA(ClassB):
    def __init__(self, params):
        super().__init__(params)
        # other params

    def get_current_attr(self):
        sql = "SELECT max(attr) FROM {};".format(self.table_name)
        self.rs_cursor.execute(sql)
        current_attr = self.rs_cursor.fetchone()[0]
        return current_attr

# classb.py
import psycopg2

class ClassB:
    def __init__(self, params):
        self.redshift_conn = self.open_redshift_connection()
        self.redshift_conn.set_isolation_level(
            psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
        self.rs_cursor = self.redshift_conn.cursor()
        self.table_name = "atablename"

    def open_redshift_connection(self):
        return psycopg2.connect()

然后

from unittest import TestCase, mock
from classa import ClassA

class Tester(TestCase):
    @mock.patch("classb.psycopg2")
    def test_get_current_attr(self, mock_psycopg2):
        mock_cur = mock_psycopg2.connect().cursor()
        mock_cur.fetch_one.return_value = 1

        a = ClassA({})
        result = a.get_current_attr()

        mock_cur.execute.assert_called_with(
            "SELECT max(attr) FROM {};".format(a.table_name)
        )

关于来自基类的 Python 模拟 psycopg2,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46085380/

相关文章:

grails - 模拟标准计数api grails/groovy

python - Docker 公开容器之间的端口

python - 将选项卡扩展到整个窗口大小?

python - networkx.MultiDiGraph.edges 方法是否保持顺序?

python - 在Windows上安装python 3和python2.7

python - 如何绘制非数字列的直方图 w.r.t pandas 数据框中的另一个计算列?

python - 如何使用 Mock @patch 获取调用计数?

mocking - 如何验证链式方法调用?

Python 代码随机卡住

PostgreSQL psycopg2 返回一个字符串元组而不是元组的元组?