mock で読み取り専用プロパティをどのようにモックしますか?
私は試した:
setattr(obj.__class__, 'property_to_be_mocked', mock.Mock())
しかし、問題はクラスのすべてのインスタンスに適用されることです...私のテストを中断します。
他にアイデアはありますか?オブジェクト全体をモックしたくはありません。この特定のプロパティのみをモックしたいと思います。
__get__
メソッドを直接モックするよりも、プロパティをPropertyMock
としてモックする方が良いと思います。
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()
実際、答えは documentation で(いつものように)でした。例に従っているとき、クラスではなくインスタンスにパッチを適用しただけです。
方法は次のとおりです。
class MyClass:
@property
def last_transaction(self):
# an expensive and complicated DB query here
pass
テストスイートで:
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
おそらくスタイルの問題ですが、テストでデコレーターを好む場合は、@ 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()
プロパティをオーバーライドするオブジェクトがモックオブジェクトの場合、patch
を使用する必要はありません。
代わりに、 PropertyMock
を作成してから、モックのtypeのプロパティをオーバーライドできます。たとえば、mock_rows.pages
プロパティをオーバーライドして(mock_page, mock_page,)
を返すには:
mock_page = mock.create_autospec(reader.ReadRowsPage)
# TODO: set up mock_page.
mock_pages = mock.PropertyMock(return_value=(mock_page, mock_page,))
type(mock_rows).pages = mock_pages
モックされたプロパティにアクセスしたかどうかをテストしたくない場合は、期待されるreturn_value
。
with mock.patch(MyClass, 'last_transaction', Transaction()):
...