클래스 조롱:모의() 또는 패치()?
저는 Python과 함께 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>
patch
대체MyClass
호출하는 함수에서 클래스의 사용을 제어할 수 있는 방식으로.클래스에 패치를 적용하면 클래스에 대한 참조가 모의 인스턴스로 완전히 대체됩니다.
mock.patch
일반적으로 테스트 내부에 클래스의 새 인스턴스를 만드는 무언가를 테스트할 때 사용됩니다. mock.Mock
인스턴스가 더 명확하고 선호됩니다.만약 당신이self.sut.something
메서드가 인스턴스를 생성했습니다.MyClass
인스턴스를 매개 변수로 받는 대신,mock.patch
여기가 적절할 것입니다.
저는 이것에 대한 유튜브 영상을 가지고 있습니다.
단답:사용하다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)
unittest.mock 작업 시 차이점을 설명하고 지침을 제공하는 핵심 사항
- 테스트 대상 객체의 일부 인터페이스 요소(인수 전달)를 바꾸려면 Mock 사용
- 테스트 대상 개체의 일부 개체 및 가져온 모듈에 대한 내부 호출을 바꾸려면 패치를 사용합니다.
- 항상 조롱하는 개체의 사양을 제공합니다.
- 패치를 사용하면 항상 자동 사양을 제공할 수 있습니다.
- Mock을 사용하면 사양을 제공할 수 있습니다.
- Mock 대신 create_autospec을 사용할 수 있습니다. create_autospec은 규격을 사용하여 Mock 객체를 생성하기 위한 것입니다.
위의 질문에서 정답은 다음과 같습니다.Mock
또는 더 정확히 말하면.create_autospec
(당신이 조롱하는 클래스의 모의 방법에 스펙을 추가할 것이기 때문에), 정의된.spec
존재하지 않는 클래스의 메서드를 호출하려는 경우(서명에 관계없이) 모의에서 도움이 될 것입니다. 몇 가지를 확인하십시오.
from unittest import TestCase
from unittest.mock import Mock, create_autospec, patch
class MyClass:
@staticmethod
def method(foo, bar):
print(foo)
def something(some_class: MyClass):
arg = 1
# Would fail becuase of wrong parameters passed to methd.
return some_class.method(arg)
def second(some_class: MyClass):
arg = 1
return some_class.unexisted_method(arg)
class TestSomethingTestCase(TestCase):
def test_something_with_autospec(self):
mock = create_autospec(MyClass)
mock.method.return_value = True
# Fails because of signature misuse.
result = something(mock)
self.assertTrue(result)
self.assertTrue(mock.method.called)
def test_something(self):
mock = Mock() # Note that Mock(spec=MyClass) will also pass, because signatures of mock don't have spec.
mock.method.return_value = True
result = something(mock)
self.assertTrue(result)
self.assertTrue(mock.method.called)
def test_second_with_patch_autospec(self):
with patch(f'{__name__}.MyClass', autospec=True) as mock:
# Fails because of signature misuse.
result = second(mock)
self.assertTrue(result)
self.assertTrue(mock.unexisted_method.called)
class TestSecondTestCase(TestCase):
def test_second_with_autospec(self):
mock = Mock(spec=MyClass)
# Fails because of signature misuse.
result = second(mock)
self.assertTrue(result)
self.assertTrue(mock.unexisted_method.called)
def test_second_with_patch_autospec(self):
with patch(f'{__name__}.MyClass', autospec=True) as mock:
# Fails because of signature misuse.
result = second(mock)
self.assertTrue(result)
self.assertTrue(mock.unexisted_method.called)
def test_second(self):
mock = Mock()
mock.unexisted_method.return_value = True
result = second(mock)
self.assertTrue(result)
self.assertTrue(mock.unexisted_method.called)
정의된 규격이 사용된 테스트 사례는 다음에서 메서드를 호출했기 때문에 실패합니다.something
그리고.second
함수는 MyClass에 불만이 없습니다. 즉, 버그를 잡는 반면 기본값입니다.Mock
표시됩니다.
참고로 patch.object를 사용하여 호출되는 클래스 메서드만 조롱하는 옵션이 하나 더 있습니다.
클래스가 기능의 내부 부분으로 사용되는 경우 패치의 좋은 사용 사례는 다음과 같습니다.
def something():
arg = 1
return MyClass.method(arg)
그러면 패치를 장식품으로 사용하여 My Class를 조롱하고 싶을 것입니다.
언급URL : https://stackoverflow.com/questions/8180769/mocking-a-class-mock-or-patch
'programing' 카테고리의 다른 글
루비의 콘솔에서 입력을 읽으시겠습니까? (0) | 2023.06.05 |
---|---|
파이어베이스 이후로 지금 어떤 방법을 사용해야 합니까?InstanceId.getInstance().getToken()이 더 이상 사용되지 않습니다. (0) | 2023.06.05 |
Firebase 저장소:디렉터리를 삭제하는 방법 (0) | 2023.06.05 |
R 사용자 전문가, 의 기능.R 프로파일? (0) | 2023.06.05 |
dplyr을 사용하여 중복된 행 제거 (0) | 2023.06.05 |