【发布时间】:2016-08-09 15:27:00
【问题描述】:
我在测试 python 3.4 中的 with 中会引发的异常时遇到问题。我只是无法为这种代码和平运行测试:
import logging
...
class Foo(object):
...
def foo(self, src, dst):
try:
with pysftp.Connection(self._host, username=self._username, password=self._password) as connection:
connection.put(src, dst)
connection.close()
except (
ConnectionException,
CredentialException,
SSHException,
AuthenticationException,
HostKeysException,
PasswordRequiredException
) as e:
self._log.error(e)
这就是我想要测试它的方式:
import logging
...
class TestFoo(TestCase):
@parameterized.expand([
('ConnectionException', ConnectionException),
('CredentialException', CredentialException),
('SSHException', SSHException),
('AuthenticationException', AuthenticationException),
('HostKeysException', HostKeysException),
('PasswordRequiredException', PasswordRequiredException),
])
@patch('pysftp.Connection', spec_set=pysftp.Connection)
def test_foo_exceptions(self, _, ex, sftp_mock):
"""
NOTE: take a look at:
http://stackoverflow.com/questions/37014904/mocking-python-class-in-unit-test-and-verifying-an-instance
to get an understanding of __enter__ and __exit__
"""
sftp_mock.return_value = Mock(
spec=pysftp.Connection,
side_effect=ex,
__enter__ = lambda self: self,
__exit__ = lambda *args: None
)
foo = Foo('host', 'user', 'pass', Mock(spec_set=logging.Logger))
foo.foo('src', 'dst')
self.assertEqual(foo._log.error.call_count, 1)
但它失败了 - 输出:
Failure
...
AssertionError: 0 != 1
【问题讨论】:
-
您的意思是“
pysftp.Connection实例化中的异常”还是调用connection.something()时的异常? -
你说的
with是什么意思?什么引发了异常?您创建用于with的上下文管理器?还是上下文管理器应该处理由with管理的块中引发的异常? -
您将引发异常作为创建上下文管理器的副作用(
pysftp.Connection(..)调用会引发它)。with语句永远不会将其用作上下文管理器,with管理的块也不会被执行。因此,您的代码正确地执行了try:...except ..语句,但您不需要任何上下文管理器知识。那么出现问题的是记录器是如何被调用的。 -
Foo.__init__究竟对第四个位置参数做了什么?它是被调用还是直接存储为self._log? -
@ForceBru 我的意思是 pysftp.Connection 中的异常
标签: python unit-testing mocking nose python-mock