私の理解では、MagicMockはMockのスーパーセットであり、自動的に「マジック メソッド」を実行するため、リスト、反復などをシームレスにサポートします...では、プレーンなMockが存在する理由は何ですか? それは、事実上無視できるMagicMockの単純なバージョンではありませんか? MockクラスはMagicMockで利用できないトリックを知っていますか?
5 に答える
プレーンなモックが存在する理由は何ですか?
Mock の作者である Michael Foord は、Pycon 2011 (31:00) で非常によく似た質問に答えました。
Q:なぜ MagicMock は、デフォルトのモック オブジェクトにアビリティを組み込むのではなく、別のものにしたのですか?
A:合理的な答えの 1 つは、MagicMock の動作方法は、新しいモックを作成して設定することにより、これらすべてのプロトコル メソッドを事前に構成することです。したがって、すべての新しいモックが一連の新しいモックを作成し、それらをプロトコル メソッドとして設定し、それらすべてのプロトコルを設定するとします。メソッドはさらに多くのモックを作成し、それらをプロトコルメソッドに設定すると、無限の再帰が得られます...
モックをコンテナー オブジェクトとしてアクセスしてエラーにしたい場合はどうすればよいでしょうか? それを機能させたくありませんか? すべてのモックがすべてのプロトコル メソッドを自動的に取得する場合、それを行うのははるかに困難になります。また、MagicMock はこの事前構成の一部を行い、適切ではない可能性のある戻り値を設定します。そのため、すべてが事前構成されて利用可能になっているこの便利なものを使用する方がよいと考えましたが、通常のモックを使用することもできます。オブジェクトを作成し、存在させたい魔法のメソッドを設定するだけです...
簡単な答えは次のとおりです。必要な動作であればどこでも MagicMock を使用してください。
まず、MagicMock
は のサブクラスですMock
。
class MagicMock(MagicMixin, Mock)
その結果、MagicMock は、Mock が提供するすべてのものとそれ以上のものを提供します。Mock を MagicMock の簡易バージョンと考えるのではなく、MagicMock を Mock の拡張バージョンと考えてください。これは、Mock が存在する理由と、Mock が MagicMock の上に提供するものについての質問に対処する必要があります。
第二に、MagicMock は多く/ほとんどのマジック メソッドのデフォルト実装を提供しますが、Mock は提供しません。提供されているマジック メソッドの詳細については、こちらを参照してください。
提供されているマジック メソッドの例:
>>> int(Mock())
TypeError: int() argument must be a string or a number, not 'Mock'
>>> int(MagicMock())
1
>>> len(Mock())
TypeError: object of type 'Mock' has no len()
>>> len(MagicMock())
0
そして、これらは直感的ではないかもしれません(少なくとも私には直感的ではありません):
>>> with MagicMock():
... print 'hello world'
...
hello world
>>> MagicMock()[1]
<MagicMock name='mock.__getitem__()' id='4385349968'>
これらのメソッドが初めて呼び出されると、MagicMock に追加されたメソッドを「見る」ことができます。
>>> magic1 = MagicMock()
>>> dir(magic1)
['assert_any_call', 'assert_called_once_with', ...]
>>> int(magic1)
1
>>> dir(magic1)
['__int__', 'assert_any_call', 'assert_called_once_with', ...]
>>> len(magic1)
0
>>> dir(magic1)
['__int__', '__len__', 'assert_any_call', 'assert_called_once_with', ...]
では、常に MagicMock を使用してみませんか?
あなたへの質問は次のとおりです。デフォルトのマジック メソッドの実装でよろしいですか? 例えば、mocked_object[1]
エラーにならなくてもいいですか?マジック メソッドの実装が既に存在するために意図しない結果が生じても大丈夫ですか?
これらの質問に対する答えが「はい」の場合は、MagicMock を使用してください。それ以外の場合は、モックに固執します。
これは、pythonの公式ドキュメントに次のように記載され ています。
これらの例のほとんどで、Mock クラスと MagicMock クラスは交換可能です。MagicMock はより有能なクラスであるため、デフォルトで使用するのに適切なクラスになります。