2011-11-18 12 views
78

私はmockをPythonで使用していますが、どちらの方法がどちらの方が優れているのか不思議に思っていました(読む:もっとpythonic)。クラスを模擬する:Mock()かpatch()?

方法1:モックオブジェクトを作成して使用してください。モックを作成するには、パッチの使用:

def test_one (self): 
    mock = Mock() 
    mock.method.return_value = True 
    self.sut.something(mock) # This should called mock.method and checks the result. 
    self.assertTrue(mock.method.called) 

方法2:コードは次のようになります。コードは次のようになります。

@patch("MyClass") 
def test_two (self, mock): 
    instance = mock.return_value 
    instance.method.return_value = True 
    self.sut.something(instance) # This should called mock.method and checks the result. 
    self.assertTrue(instance.method.called) 

どちらの方法も同じです。私はその違いを確信していません。

誰でも私を啓発できますか?

+9

、私は私が何も理解していないにも関わらず、最初のバージョンは明確であり、あなたがやりたいことを示していることを感じます実際の違い。私はこれが何か助けであるかどうかわからないが、私は、初心者のプログラマーが感じるかもしれないものを伝えることが有用かもしれないと思った。 –

+1

@MichaelBrennan:ご意見ありがとうございます。それは確かに有用です。 – Sardathrion

答えて

107

mock.patchは、mock.Mockと非常に異なるです。 patchは、クラスをmockオブジェクトに置き換えて、mockインスタンスで作業できるようにします。このスニペットを見てみましょう:

>>> class MyClass(object): 
... def __init__(self): 
...  print 'Created [email protected]{0}'.format(id(self)) 
... 
>>> def create_instance(): 
... return MyClass() 
... 
>>> x = create_instance() 
Created [email protected] 
>>> 
>>> @mock.patch('__main__.MyClass') 
... def create_instance2(MyClass): 
... MyClass.return_value = 'foo' 
... return create_instance() 
... 
>>> i = create_instance2() 
>>> i 
'foo' 
>>> def create_instance(): 
... print MyClass 
... return MyClass() 
... 
>>> create_instance2() 
<mock.Mock object at 0x100505d90> 
'foo' 
>>> create_instance() 
<class '__main__.MyClass'> 
Created [email protected] 
<__main__.MyClass object at 0x100505d90> 

patchはあなたが呼び出す関数でクラスの使用を制御することを可能にする方法でMyClassを置き換えます。クラスにパッチを適用すると、そのクラスへの参照はモックインスタンスに完全に置き換えられます。

mock.patchは、通常、テスト内でクラスの新しいインスタンスを作成するものをテストするときに使用されます。 mock.Mockインスタンスがより明確になり、優先されます。 self.sut.somethingメソッドがインスタンスをパラメータとして受け取る代わりにMyClassのインスタンスを作成した場合は、ここでmock.patchが適切です。

+2

@ D.Shawleyテストする必要がある別のクラスの内部でインスタンス化されたクラスにどのようにパッチを当てるのですか? – ravi404

+4

@ravz - [Where to Patch](https://mock.readthedocs.org/en/latest/patch.html#where-to-patch)に読んでください。これは、適切に動作するためにはもっと難しいことの一つです。 –

+0

私のモックテストは**メソッド2 **に似ています。 MyClassインスタンスで例外を発生させたい私はmock.side_effectとmock.return_value.side_effectの両方を試しましたが、それらは動作しませんでした。私は何をしますか? – Hussain

4

私はこれにYouTube videoを持っています。

短い答え:あなたが嘲笑したいものを渡しているときはmock、そうでなければpatchを使ってください。 2つのうち、モックは強く推奨されます。これは、あなたが適切な依存関係注入を使ってコードを書いていることを意味するからです。

愚か例:モック()またはパッチのいずれかを試したことがない人として

# Use a mock to test this. 
my_custom_tweeter(twitter_api, sentence): 
    sentence.replace('cks','x') # We're cool and hip. 
    twitter_api.send(sentence) 

# Use a patch to mock out twitter_api. You have to patch the Twitter() module/class 
# and have it return a mock. Much uglier, but sometimes necessary. 
my_badly_written_tweeter(sentence): 
    twitter_api = Twitter(user="XXX", password="YYY") 
    sentence.replace('cks','x') 
    twitter_api.send(sentence)