2012-08-06 3 views
47

어떻게 읽기 전용 속성을 mock으로 조롱합니까? 읽기 전용 속성을 모의로 조롱하는 법?

내가 시도 :

setattr(obj.__class__, 'property_to_be_mocked', mock.Mock()) 

하지만 문제는 그 다음 내 테스트를 나누기 클래스 ...의 모든 인스턴스에 적용됩니다.

다른 생각이 있으십니까? 전체 개체를 조롱하고 싶지는 않지만이 특정 속성 만 모의하고 싶습니다.

답변

37

실제로 대답은 (평소와 같이) documentation이었습니다. 그 예를 따랐을 때 클래스 대신 인스턴스에 패치를 적용한다는 것입니다.

def test(): 
    # Make sure you patch on MyClass, not on a MyClass instance, otherwise 
    # you'll get an AttributeError, because mock is using settattr and 
    # last_transaction is a readonly property so there's no setter. 
    with mock.patch(MyClass, 'last_transaction') as mock_last_transaction: 
     mock_last_transaction.__get__ = mock.Mock(return_value=Transaction()) 
     myclass = MyClass() 
     print myclass.last_transaction 
+6

사람들은 다른 예를 사용해야합니다. 'mock.PropertyMock'은 그것을 할 수있는 방법입니다! – vitiral

73

내가 __get__ 방법을 조롱하기보다는, 더 나은 방법은 PropertyMock으로 재산을 조롱하는 것입니다 생각 : 테스트 스위트에서

class MyClass: 
    @property 
    def last_transaction(self): 
     # an expensive and complicated DB query here 
     pass 

: 여기

그것을 수행하는 방법이다 직접.

documentation에는 unittest.mock.PropertyMock : 을 검색하십시오. 클래스의 속성 또는 다른 설명 자로 사용하도록 의도 된 모의. PropertyMock__get____set__ 메서드를 제공하므로 가져올 때 반환 값을 지정할 수 있습니다.

class MyClass: 
    @property 
    def last_transaction(self): 
     # an expensive and complicated DB query here 
     pass 

def test(unittest.TestCase): 
    with mock.patch('MyClass.last_transaction', new_callable=PropertyMock) as mock_last_transaction: 
     mock_last_transaction.return_value = Transaction() 
     myclass = MyClass() 
     print myclass.last_transaction 
     mock_last_transaction.assert_called_once_with() 
+0

'@ property'로 장식 된 클래스 메소드를 모방해야했습니다. 이 답변은 다른 답변 (및 다른 많은 질문에 대한 다른 답변)이 제시하지 않은 경우 나에게 도움이되었습니다. – AlanSE

+2

이렇게해야합니다. 나는 "받아 들여진"대답을 이동하는 방법이 있었으면 좋겠다. – vitiral

+1

문맥 관리자 호출의 반환 값을 약간 더 깔끔하게하기 위해 호출했다. ''' with mock.patch ('MyClass.last_transaction', new_callable = PropertyMock , return_value = 거래()) : ... ''' – wodow

3

아마 당신이 jamescastlefield의 answer @, 테스트에 장식을 선호하는 스타일이지만 경우에 문제가 이런 식으로 변경 될 수 있습니다 :

class MyClass: 
    @property 
    def last_transaction(self): 
     # an expensive and complicated DB query here 
     pass 

class Test(unittest.TestCase): 
    @mock.patch('MyClass.last_transaction', new_callable=PropertyMock) 
    def test(mock_last_transaction): 
     mock_last_transaction.return_value = Transaction() 
     myclass = MyClass() 
     print myclass.last_transaction 
     mock_last_transaction.assert_called_once_with() 
0

당신이 만약 돈 여기

은 어떻게 조롱 된 부동산에 액세스했는지 여부를 테스트하고 싶지 않다면 예상되는 return_value으로 간단히 패치 할 수 있습니다.

with mock.patch(MyClass, 'last_transaction', Transaction()): 
    ... 
관련 문제