私の理解では、MagicMockは自動的に「マジックメソッド」を実行するMockのスーパーセットであり、リスト、反復などのサポートをシームレスに提供します...では、プレーンMockが存在する理由は何ですか?それは、MagicMockの一部を取り除いたバージョンであり、実際には無視できますか?DOES モッククラスがで使用できないすべてのトリックを知ってMagicMockを?
私の理解では、MagicMockは自動的に「マジックメソッド」を実行するMockのスーパーセットであり、リスト、反復などのサポートをシームレスに提供します...では、プレーンMockが存在する理由は何ですか?それは、MagicMockの一部を取り除いたバージョンであり、実際には無視できますか?DOES モッククラスがで使用できないすべてのトリックを知ってMagicMockを?
回答:
Mockの作者であるMichael Foordは、Pycon 2011(31:00)で非常によく似た質問に答えました。
Q:なぜMagicMockは、デフォルトのモックオブジェクトに機能を折り畳むだけでなく、別の物を作ったのですか?
A: 1つの合理的な答えは、MagicMockが機能する方法は、新しいモックを作成して設定することにより、これらすべてのプロトコルメソッドを事前構成することです。そのため、すべての新しいモックが新しいモックの束を作成し、それらをプロトコルメソッドとして設定してから、それらすべてのプロトコルを設定します。メソッドはより多くのモックを作成し、それらをプロトコルメソッドに設定すると、無限の再帰が得られます...
コンテナーオブジェクトとしてモックにアクセスしてエラーを発生させたい場合はどうすればよいですか?すべてのモックが自動的にすべてのプロトコルメソッドを取得している場合、それを行うのははるかに困難になります。また、MagicMockはこの事前構成の一部を行い、適切でない可能性がある戻り値を設定するので、すべてが事前構成されて利用できる便利なものを用意する方が良いと思いましたが、通常のモックを使用することもできますオブジェクトを作成し、存在させたい魔法のメソッドを設定するだけです...
簡単な答えは、MagicMockを使用したい場合はどこでも使用することです。
Mockを使用すると、マジックメソッドをモックできますが、それらを定義する必要があります。MagicMockには「ほとんどの魔法のメソッドのデフォルト実装」があります。。
マジックメソッドをテストする必要がない場合は、Mockで十分であり、無関係なことをテストに取り入れることはありません。多くのマジックメソッドをテストする必要がある場合、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はより有能なクラスであるため、デフォルトで使用するのが賢明です。
simpleの Mock
方が便利な場合がある別の特定のケースを見つけました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