[python] 클래스 조롱 : Mock () 또는 patch ()?

나는 파이썬과 함께 mock 을 사용 하고 있으며 그 두 가지 접근법 중 어느 것이 더 나은지 궁금합니다 (읽기 : 더 파이썬).

방법 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)

두 방법 모두 동일한 작업을 수행합니다. 차이점이 확실하지 않습니다.

누구든지 나를 깨달을 수 있습니까?



답변

mock.patch와는 매우 다른 동물 mock.Mock입니다. 클래스를 모의 객체로 patch 대체 하고 모의 인스턴스로 작업 할 수 있습니다. 이 스 니펫을 살펴보십시오.

>>> class MyClass(object):
...   def __init__(self):
...     print 'Created MyClass@{0}'.format(id(self))
...
>>> def create_instance():
...   return MyClass()
...
>>> x = create_instance()
Created MyClass@4299548304
>>>
>>> @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 MyClass@4300234128
<__main__.MyClass object at 0x100505d90>

patchMyClass호출하는 함수에서 클래스 사용을 제어 할 수있는 방식으로 대체 됩니다. 클래스를 패치하면 클래스에 대한 참조가 모의 인스턴스로 완전히 대체됩니다.

mock.patch일반적으로 테스트 내부에 클래스의 새 인스턴스를 만드는 무언가를 테스트 할 때 사용됩니다. mock.Mock인스턴스가 더 명확하고 선호됩니다. self.sut.something메서드가 인스턴스를 MyClass매개 변수로받는 대신 인스턴스를 만든 경우 mock.patch여기에 적합합니다.


답변

이것에 대한 YouTube 비디오 가 있습니다.

짧은 대답 : mock조롱하고 싶은 것을 전달할 때 사용 하고 patch그렇지 않은 경우 사용하십시오. 두 가지 중에서 mock은 적절한 종속성 주입으로 코드를 작성하고 있음을 의미하기 때문에 강력하게 선호됩니다.

어리석은 예 :

# 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)


답변