モックvs MagicMock
私の理解では、MagicMockはMockのスーパーセットであり、自動的に「マジックメソッド」を実行するため、リスト、反復などのサポートをシームレスに提供します。プレーンモックが存在しますか? MagicMockの単純なバージョンではないので、実際には無視できますか? MockクラスはMagicMockで利用できないトリックを知っていますか?
プレーンMockが存在する理由は何ですか?
Mockの著者であるMichael Foordが Pycon 2011(31:00)で非常によく似た質問 :
Q:なぜMagicMockは、単にデフォルトのモックオブジェクトに機能を組み込むのではなく、別のものを作成したのですか?
A:1つの合理的な答えは、MagicMockの動作方法は、新しいモックを作成して設定することにより、これらすべてのプロトコルメソッドを事前設定することです。新しいモックの束を作成し、それらをプロトコルメソッドとして設定し、それらのプロトコルメソッドのすべてがさらに多くのモックを作成し、プロトコルメソッドに設定すると、無限の再帰が得られます...
コンテナオブジェクトとしてモックにアクセスすることをエラーにしたい場合はどうしますか?すべてのモックがすべてのプロトコルメソッドを自動的に取得している場合、それを行うのははるかに困難になります。また、MagicMockはこの事前設定の一部を行い、適切でない可能性のある戻り値を設定するため、事前設定されて利用可能なすべての便利なものを用意する方が良いと考えましたが、通常のモックを使用することもできますオブジェクトと単にあなたが存在したい魔法のメソッドを設定...
簡単な答えは、MagicMockを使用したい場合はどこでも使用するだけです。
Mockを使用すると、canモックマジックメソッドを定義できます。 MagicMockには 「ほとんどのマジックメソッドのデフォルト実装」 があります。
魔法のメソッドをテストする必要がない場合、Mockは適切であり、テストに多くの無関係なものを持ち込みません。多くのマジックメソッドをテストする必要がある場合、MagicMockを使用すると時間を節約できます。
まず、MagicMock
はMock
のサブクラスです。
class MagicMock(MagicMixin, Mock)
その結果、MagicMockはMockが提供するものすべてを提供します。 MockをMagicMockの簡略版と考えるのではなく、MagicMockをMockの拡張版と考えてください。これは、Mockが存在する理由と、MockがMagicMockの上に提供するものに関する質問に対処する必要があります。
第二に、MagicMockは多くの/ほとんどの魔法のメソッドのデフォルト実装を提供しますが、Mockは提供しません。提供されるマジックメソッドの詳細については、 here を参照してください。
提供されるマジックメソッドの例:
>>> 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に初めて追加されたメソッドを呼び出すと、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はより有能なクラスなので、デフォルトで使用するのが賢明なクラスになります。
私はsimpleMock
がMagicMock
よりも便利になる別の特定のケースを見つけました:
In [1]: from unittest.mock import Mock, MagicMock, ANY
In [2]: mock = Mock()
In [3]: magic = MagicMock()
In [4]: mock.foo == ANY
Out[4]: True
In [5]: magic.foo == ANY
Out[5]: False
ANY
と比較すると便利です。たとえば、モックを使用して値を計算する2つの辞書間でほとんどすべてのキーを比較します。
これは、Mock
を使用している場合に有効です。
self.assertDictEqual(my_dict, {
'hello': 'world',
'another': ANY
})
一方、AssertionError
を使用した場合は、MagicMock
が発生します