模拟psycopg2-如何引发异常?

时间:2019-12-18 22:17:16

标签: python postgresql unit-testing mocking psycopg2

我正在尝试处理psycopg2数据库的潜在执行问题。 IIRC psycopg2.DatabaseError应该处理大多数sql错误。该方法将html字符串插入full_html内的mytable列中,并返回与其关联的id

def insertPage(cursor, html):
    try:
       cursor.execute(("INSERT INTO mytable (full_html)"
        "VALUES (%s) RETURNING id"), (html,))
    except psycopg2.DatabaseError:
         print("error inserting html")

和测试:

def test_insertPage_error(self):
    mockPage = (1, 'html') # Row contains id and html string

    with patch('psycopg2.connect') as mock_connect:
        with self.assertRaises(psycopg2.DatabaseError):
            mock_cur = mock_connect.return_value.cursor.return_value
            mock_cur.fetchone.return_value = mockPage

            resultId = insertPage(mock_cur, 'html')

我在调用psycopg2.DatabaseError时遇到问题。我尝试将'html'参数替换为None或另一个不是字符串的值。我以为我的mock_cur不退还我想要的东西有问题吗?也许我误会了我提出的错误?

跟踪:

Traceback (most recent call last):
  File "/code/tests/testInsert.py", line 62, in test_insertPage_error
    resultId = insertPage(mock_cur, 'html')
AssertionError: DatabaseError not raised

1 个答案:

答案 0 :(得分:2)

您的insertPage()函数已经在捕获psycopg2.DatabaseError并打印一条消息,并且退出而没有引发其他异常。这就是DatabaseError从未使之脱离insertPage函数的原因。

尝试更改您的insertPage函数以仅进行cursor.execute调用,而没有try / except块,这将允许insertPage将异常传递到链上而不是捕获该异常:

def insertPage(cursor, html):
   cursor.execute(("INSERT INTO mytable (full_html)"
        "VALUES (%s) RETURNING id"), (html,))

或者,您可以定义一个自定义异常类型,并在遇到DatabaseError时引发它:

class SpecialDatabaseError(Exception):
    pass

def insertPage(cursor, html):
    try:
       cursor.execute(("INSERT INTO mytable (full_html)"
        "VALUES (%s) RETURNING id"), (html,))
    except psycopg2.DatabaseError:
        raise SpecialDatabaseError("This is a special error!")

然后您的模拟将断言SpecialDatabaseError被引发:

   with self.assertRaises(SpecialDatabaseError):