2012-08-06 43 views
47

あなたはどのようにmockで読み取り専用プロパティをモックしますか?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

コンテキストマネージャーの戻り値を含めて、少しきれいにしてください: '' ' mock.patch( 'MyClass.last_transaction'、new_callable = PropertyMock 、return_value = Transaction()): ... '' ' – 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()): 
    ... 
関連する問題