Reputation: 111
I have problems to test exceptions which would be raised within a with in python 3.4. I just can't get the tests run for this peace of code:
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)
And this is how I want to test it:
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)
But it fails - output:
Failure
...
AssertionError: 0 != 1
Upvotes: 1
Views: 488
Reputation: 1121824
Your sftp_mock.return_value
object is never called, so the side_effect
is never triggered and no exception is raised. It would only be called if the return value of pysftp.Connection(...)
was itself called again.
Set the side effect directly on the mock:
sftp_mock.side_effect = ex
Note that now the pysftp.Connection(...)
expression raises the exception and it no longer matters that the return value of that expression would have been used as a context manager in a with
statement.
Note that your exceptions will complain about not getting any arguments; pass in instances of your exceptions, not the type:
@parameterized.expand([
('ConnectionException', ConnectionException('host', 1234)),
# ... etc.
])
Upvotes: 1