2016-08-09 3 views
1

파이썬 3.4에서 with 내에서 발생할 예외를 테스트하는 데 문제가 있습니다. 난 그냥 테스트 코드의 평화를 실행할 수 없습니다Python 3 : 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 
+0

는'connection.something()'를 호출 할 때'pysftp.Connection' 인스턴스화의 예외 '를 의미하거나합니까? – ForceBru

+0

'with' *를 사용하여 *로 무엇을 의미합니까? 무엇이 예외를 제기합니까? 'with'에서 사용하기 위해 생성 한 컨텍스트 관리자? 아니면 컨텍스트 관리자가'with'에 의해 관리되는 블록에서 발생한 예외를 처리해야합니까? –

+0

컨텍스트 관리자의 생성 (* pysftp.Connection (..) 호출에서 발생시키는 부작용) 예외가 발생합니다. 'with' 문은 이것을 컨텍스트 관리자로 사용하지 않으며 'with'에 의해 관리되는 블록도 실행되지 않습니다. 따라서 여러분의 코드는'try : ... except ..' 문을 올바르게 실행하고 있지만 컨텍스트 관리자에 대한 지식은 필요하지 않습니다. 잘못된 것은 로거가 어떻게 나타나는지입니다. –

답변

1

sftp_mock.return_value 개체는 호출되지 않으므로 side_effect이 트리거되지 않으며 예외가 발생하지 않습니다. 반환 값pysftp.Connection(...) 인 경우에만 다시 호출됩니다.

는 모의에 직접 부작용 설정 : 이제 pysftp.Connection(...) 표현을 제외하고 더 이상 그 표현의 반환 값이 문맥으로 사용 된 것이 문제를 제기

sftp_mock.side_effect = ex 

주 관리자가 with 성명

예외가 있으면 인수가 발생하지 않는다는 것에 불만을 토로합니다. 인스턴스가 아닌 유형 귀하의 예외 전달 :

@parameterized.expand([ 
    ('ConnectionException', ConnectionException('host', 1234)), 
    # ... etc. 
]) 
+0

의 결과는 다음과 같습니다.'TypeError : __init __() 2 개의 필수 위치 인수 : 'host'및 'port'' –

+0

@LarsGrundei : 아, 예외가 발생합니다. 클래스가 아닌 인스턴스를 제공해야합니다. 'raise pysftp.ConnectionException'와 같은 에러를 재현 할 수 있습니다. –

+0

정말 고마워요. :) –

관련 문제