모의 대 MagicMock


138

내 이해는 MagicMock 이 "매직 메서드"를 자동으로 수행하여 목록, 반복 등을 완벽하게 지원하는 Mock 의 상위 집합 이라는 것입니다. 그렇다면 일반 Mock이 존재 하는 이유는 무엇 입니까? 실제로 무시할 수 있는 제거 된 MagicMock 버전이 아닌가 ? 합니까 모의 클래스에서 사용할 수없는 어떠한 트릭도 알고 MagicMock를 ?

답변:


99

일반 모의가 존재 하는 이유는 무엇입니까 ?

Mock의 작가 인 Michael Foord 는 Pycon 2011 (31:00)에서 매우 비슷한 질문을했습니다 .

Q : 왜 MagicMock이 기본 모의 객체로 기능을 접는 대신 별도의 것을 만들었습니까?

A : 하나의 합리적인 대답은 MagicMock이 작동하는 방식은 새로운 Mocks를 생성하고 설정하여 이러한 모든 프로토콜 방법을 사전 구성한다는 것입니다. 메소드는 많은 모의를 만들고 프로토콜 메소드에 설정하면 무한 재귀를 얻습니다 ...

컨테이너 객체로 모의 객체에 오류가 있기를 원한다면 어떻게해야합니까? 모든 모의가 자동으로 모든 프로토콜 방법을 가지고 있다면 그렇게하기가 훨씬 더 어려워집니다. 또한 MagicMock 은이 사전 구성 중 일부를 수행하여 적절하지 않은 반환 값을 설정하므로 모든 것이 사전 구성되어 사용 가능한 편리한 편의를 갖는 것이 더 좋을 것이라고 생각했지만 일반적인 모의를 취할 수도 있습니다 객체를 선택하고 존재하는 마법 방법을 구성하십시오 ...

간단한 답변은 : 원하는 동작이라면 어디에서나 MagicMock을 사용하십시오.


12
더 나은 대답은 다음과 같습니다. 수행중인 작업을 알고 있으면 MagicMock을 사용하고 그렇지 않으면 Mock을 사용하십시오.
laike9m

56

Mock을 사용하면 마술 방법을 조롱 할 있지만 정의해야합니다. MagicMock에는 "대부분의 매직 메소드의 기본 구현"이 있습니다. .

마법 방법을 테스트 할 필요가 없다면 Mock이 적합하며 테스트에 많은 외적인 것들을 가져 오지 않습니다. 많은 마법 방법을 테스트해야하는 경우 MagicMock이 시간을 절약 해줍니다.


물론 나는 이미 문서를 읽었습니다. 그것은 내 질문에 대답하지 않습니다-MagicMock이 정확히 같은 플러스를 더 많이한다면 왜 평범한 Mock을 귀찮게합니까? 내 테스트에서 사물을 보지 못합니다. 다른 이름 만 사용하면됩니다. 캐치는 어디에 있습니까?
블라디미르 이그나 토프

39
테스트는 최소화해야하고 모의 객체는 최소한의 기능을 수행하여 테스트중인 것을 정확히 확인할 수 있습니다. 더 많은 기능만으로 MagicMock을 사용하지만 "더 많은"기능을 명시 적으로 테스트하지 않는 경우 기본 MagicMock 동작으로 인해 테스트가 실패 할 위험이 있습니다. 이 실패는 MagicMock의 기본 설정에 대한 것보다 더 많은 것을 반영 할 수 있습니다. 더 나쁜 것은 테스트 가 실패했을 때 성공할 위험이 있다는 것입니다 . 위험은 작지만이 경우 많은 시간이 낭비됩니다.
Sean Redmond

1
나는 일반 JS 대 Jquery를 사용하는 것처럼 생각합니다. 물론, Jquery를 사용하여 모든 JS를 수행 할 있지만 경우에 따라 작업을 완료하는 데 필요한 최소한의 도구 만 사용하려고합니다. 이러한 사례는 대개 매우 단순하거나 매우 복잡한 것으로 나타났습니다.
snuggles

49

로 시작 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을 사용하십시오. 그렇지 않으면 Mock을 고수하십시오.


12

이것은 파이썬의 공식 문서가 말하는 것입니다 :

이러한 대부분의 예에서 Mock 클래스와 MagicMock 클래스는 서로 바꿔 사용할 수 있습니다. MagicMock이 더 유능한 클래스이기 때문에 기본적으로 사용하기에 적합한 클래스입니다.


3

단순함 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예를 들어 모의를 사용하여 일부 값을 계산하는 두 사전 사이의 거의 모든 키를 비교하는 것과 비교하면 유용 할 수 있습니다.

다음을 사용하는 경우 유효합니다 Mock.


self.assertDictEqual(my_dict, {
  'hello': 'world',
  'another': ANY
})

그것은을 올릴 때 AssertionError사용한 한 경우MagicMock

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.