TestCase - 模拟时 with 语句中未引发异常 __enter__
TestCase - Exception not raised in with statement when mocking __enter__
我正在尝试测试包含 with
语句的 Python 方法。 with
语句中的代码可以引发 RuntimeError
。我正在谈论的测试测试 RuntimeError
是否被引发。
__enter__
和 __exit__
方法很重(通常打开和关闭 SSH 连接),我在测试时模拟它们。
这里是我要测试的方法的简化定义:
# client.py
class Client():
def method_to_test():
with self:
raise RuntimeError()
为了清楚起见,我省略了__enter__
和__exit__
的定义,并删除了method_to_test
中所有与当前问题无关的代码。
为了测试此方法,我模拟了 __enter__
和 __exit__
,并检查是否引发了 RuntimeError
:
# tests.py
from django.test import TestCase
import mock
from .client import Client
class ClientTestCase(TestCase):
@mock.patch('mymodule.client.Client.__enter__')
@mock.patch('mymodule.client.Client.__exit__')
def test_method_raises_Runtime(self, mock_exit, mock_enter):
mock_enter.return_value = None
client = Client()
with self.assertRaises(RuntimeError):
client.method_to_test()
此测试失败:AssertionError: RuntimeError not raised
如果我不模拟 __enter__
,则会引发 RuntimeError
。为什么模拟 __enter__
会使这个测试失败?
见于 PEP343 https://www.python.org/dev/peps/pep-0343/
The exception is swallowed if exit() returns true
由于self.__exit__
是Client.method_to_test
中的一个MagicMock
,self.__exit__
return是一个MagicMock
,求值为True
。 RuntimeError
被吞了。
修复很简单。 self.__exit__()
as to return None
instead of a MagicMock
:
# tests.py
from django.test import TestCase
import mock
from .client import Client
class ClientTestCase(TestCase):
@mock.patch('mymodule.client.Client.__enter__')
@mock.patch('mymodule.client.Client.__exit__')
def test_method_raises_Runtime(self, mock_exit, mock_enter):
# __exit__ returns None, evaluated as False
mock_exit.return_value = None
mock_enter.return_value = None
client = Client()
with self.assertRaises(RuntimeError):
client.method_to_test()
我正在尝试测试包含 with
语句的 Python 方法。 with
语句中的代码可以引发 RuntimeError
。我正在谈论的测试测试 RuntimeError
是否被引发。
__enter__
和 __exit__
方法很重(通常打开和关闭 SSH 连接),我在测试时模拟它们。
这里是我要测试的方法的简化定义:
# client.py
class Client():
def method_to_test():
with self:
raise RuntimeError()
为了清楚起见,我省略了__enter__
和__exit__
的定义,并删除了method_to_test
中所有与当前问题无关的代码。
为了测试此方法,我模拟了 __enter__
和 __exit__
,并检查是否引发了 RuntimeError
:
# tests.py
from django.test import TestCase
import mock
from .client import Client
class ClientTestCase(TestCase):
@mock.patch('mymodule.client.Client.__enter__')
@mock.patch('mymodule.client.Client.__exit__')
def test_method_raises_Runtime(self, mock_exit, mock_enter):
mock_enter.return_value = None
client = Client()
with self.assertRaises(RuntimeError):
client.method_to_test()
此测试失败:AssertionError: RuntimeError not raised
如果我不模拟 __enter__
,则会引发 RuntimeError
。为什么模拟 __enter__
会使这个测试失败?
见于 PEP343 https://www.python.org/dev/peps/pep-0343/
The exception is swallowed if exit() returns true
由于self.__exit__
是Client.method_to_test
中的一个MagicMock
,self.__exit__
return是一个MagicMock
,求值为True
。 RuntimeError
被吞了。
修复很简单。 self.__exit__()
as to return None
instead of a MagicMock
:
# tests.py
from django.test import TestCase
import mock
from .client import Client
class ClientTestCase(TestCase):
@mock.patch('mymodule.client.Client.__enter__')
@mock.patch('mymodule.client.Client.__exit__')
def test_method_raises_Runtime(self, mock_exit, mock_enter):
# __exit__ returns None, evaluated as False
mock_exit.return_value = None
mock_enter.return_value = None
client = Client()
with self.assertRaises(RuntimeError):
client.method_to_test()