2011-11-18 3 views
78

나는 파이썬에서 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) 

방법 : 같은 코드가 보인다. 코드는 다음과 같습니다.

@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.patchmock.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 인스턴스로 완전히 대체됩니다.

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을 사용하십시오. 두 가지 중에서, 모의가 강하게 선호되는 이유는 적절한 의존성 주입으로 코드를 작성한다는 것을 의미하기 때문입니다.

바보 예 : 모의() 또는 패치 중 하나를 해본 적이있는 사람으로

# 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) 
관련 문제