使用 Pytest 在函数中模拟 Raise Exception
Mocking Raise Exception in function with Pytest
我有以下功能get_postgres_connection。我正在尝试 运行 带有 test_get_postgres_connection_unsuccess 的单元测试以触发异常。
def get_postgres_connection():
try:
conn = psycopg2.connect(dbname = POSTGRES_DATABASE,
user = POSTGRES_USER,
password = POSGRES_PASSWORD,
host = POSTGRES_HOST,
port = POSTGRES_PORT)
conn.autocommit = True
return conn
except Exception as err:
logging.error('Unable to connect to postgres db: %s', err)
def test_get_postgres_connection_unsuccess(monkeypatch):
""" tests an exception is hit if the connection to postgres is unsuccesful"""
# setup
class mock_conn:
def __init__(self, dbname, user, password, host, port):
raise ConnectionError('This fake connection did not work')
autocommit = False
monkeypatch.setattr(psycopg2, 'connect', mock_conn)
我无法在模拟函数中成功引发异常。有人知道我在这里做错了什么吗?
编辑:稍微清理了代码
无需创建自己的模拟 class - 请改用 unittest.mock.MagicMock
。
您可以使用 MagicMock
实例来模拟基本上任何东西,包括第三方函数。如果添加 side_effect=Exception()
参数,则在调用模拟时会引发异常。
Python 甚至允许您在上下文管理器中执行此操作(with ...
语句),以便一旦上下文管理器块结束,模拟函数就会“取消模拟”。
最小示例:
def some_external_lib(): # this is psycopg2.connect in your example
pass
def my_func(): # this is get_postgres_connection in your example
try:
some_external_lib()
except Exception as e:
print(f"Error found: {e}")
import unittest
from unittest import mock
class TestMyFunc(unittest.TestCase):
def test_my_func_external_lib_raises_exception(self):
with mock.patch('__main__.some_external_lib', side_effect=Exception("ERROR")):
my_func()
# Running example - prints the error message
t = TestMyFunc()
t.test_my_func_external_lib_raises_exception()
请注意,正如编写的那样,该测试目前实际上并未测试任何内容。查看 get_postgres_connection
函数的主体,您可能想测试它是否 returns None
,以及是否将某些内容写入日志文件,前提是外部库引发了异常。
这是我如何使用 mock 修复测试函数,正如上面的回答
def test_get_postgres_connection_unsuccess():
""" tests an exception is hit if the connection to postgres is unsuccesful"""
# assert
with mock.patch('psycopg2.connect', side_effect=Exception('ERROR')):
self.pg_db.get_postgres_connection()
我有以下功能get_postgres_connection。我正在尝试 运行 带有 test_get_postgres_connection_unsuccess 的单元测试以触发异常。
def get_postgres_connection():
try:
conn = psycopg2.connect(dbname = POSTGRES_DATABASE,
user = POSTGRES_USER,
password = POSGRES_PASSWORD,
host = POSTGRES_HOST,
port = POSTGRES_PORT)
conn.autocommit = True
return conn
except Exception as err:
logging.error('Unable to connect to postgres db: %s', err)
def test_get_postgres_connection_unsuccess(monkeypatch):
""" tests an exception is hit if the connection to postgres is unsuccesful"""
# setup
class mock_conn:
def __init__(self, dbname, user, password, host, port):
raise ConnectionError('This fake connection did not work')
autocommit = False
monkeypatch.setattr(psycopg2, 'connect', mock_conn)
我无法在模拟函数中成功引发异常。有人知道我在这里做错了什么吗?
编辑:稍微清理了代码
无需创建自己的模拟 class - 请改用 unittest.mock.MagicMock
。
您可以使用 MagicMock
实例来模拟基本上任何东西,包括第三方函数。如果添加 side_effect=Exception()
参数,则在调用模拟时会引发异常。
Python 甚至允许您在上下文管理器中执行此操作(with ...
语句),以便一旦上下文管理器块结束,模拟函数就会“取消模拟”。
最小示例:
def some_external_lib(): # this is psycopg2.connect in your example
pass
def my_func(): # this is get_postgres_connection in your example
try:
some_external_lib()
except Exception as e:
print(f"Error found: {e}")
import unittest
from unittest import mock
class TestMyFunc(unittest.TestCase):
def test_my_func_external_lib_raises_exception(self):
with mock.patch('__main__.some_external_lib', side_effect=Exception("ERROR")):
my_func()
# Running example - prints the error message
t = TestMyFunc()
t.test_my_func_external_lib_raises_exception()
请注意,正如编写的那样,该测试目前实际上并未测试任何内容。查看 get_postgres_connection
函数的主体,您可能想测试它是否 returns None
,以及是否将某些内容写入日志文件,前提是外部库引发了异常。
这是我如何使用 mock 修复测试函数,正如上面的回答
def test_get_postgres_connection_unsuccess():
""" tests an exception is hit if the connection to postgres is unsuccesful"""
# assert
with mock.patch('psycopg2.connect', side_effect=Exception('ERROR')):
self.pg_db.get_postgres_connection()