私はPython 3.4でwithの中で発生する例外をテストするのに問題があります。Python 3:で例外をテストする方法は?
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を() 'を呼び出す意味しますか? – ForceBru
'with' *で*を意味しますか?何が例外を提起するのですか? 'with'で使用するために作成するコンテキストマネージャ?あるいは、コンテキストマネージャは、 'with'によって管理されているブロックで発生した例外を処理することになっていますか? –
あなたのコンテキストマネージャの副作用として例外を発生させています( 'pysftp.Connection(..)'呼び出しで呼び出されます)。 'with'ステートメントは、それをコンテキストマネージャーとして使用することは決してなく、' with'によって管理されるブロックも実行されません。したがって、あなたのコードは 'try:... except ..'文を正しく実行していますが、コンテキストマネージャの知識は必要ありません。間違っているのは、ロガーがどのように呼び出されるかということです。 –