"unittest.mock" --- 모의 객체 라이브러리
****************************************

버전 3.3에 추가.

**소스 코드:** Lib/unittest/mock.py

======================================================================

"unittest.mock"은 파이썬에서 테스트하기 위한 라이브러리입니다. 테스트
대상 시스템의 일부를 모의 객체로 교체하고 그들이 사용된 방식에 대해 어
서션(assertion)을 할 수 있습니다.

"unittest.mock"은 핵심 "Mock" 클래스를 제공하여 테스트 스위트 전체에
걸쳐 많은 스텁을 만들 필요가 없도록 합니다. 작업을 수행한 후, 사용된
메서드 / 어트리뷰트와 호출에 제공된 인자에 대한 어서션을 할 수 있습니
다. 일반적인 방법으로 반환 값을 지정하고 필요한 어트리뷰트를 설정할 수
도 있습니다.

또한, mock은 테스트 스코프 내에서 모듈과 클래스 수준 어트리뷰트의 패치
를 처리하는 "patch()" 데코레이터를 고유한 객체 생성을 위한 "sentinel"
과 함께 제공합니다. "Mock", "MagicMock" 및 "patch()" 사용 방법에 대한
몇 가지 예는 간략 지침을 참조하십시오.

Mock은 사용하기 매우 쉽고 "unittest"와 함께 사용하도록 설계되었습니다.
Mock은 많은 모킹(mocking) 프레임워크에서 사용하는 '기록(record) -> 재
생(replay)' 대신 '액션(action) -> 어서션(assertion)' 패턴을 기반으로
합니다.

이전 버전의 파이썬을 위한 "unittest.mock"의 역 이식이 있습니다, PyPI의
mock에서 제공됩니다.


간략 지침
=========

"Mock"과 "MagicMock" 객체는 그것들을 액세스함에 따라 모든 어트리뷰트와
메서드를 작성하고 사용 방식에 대한 세부 사항을 저장합니다. 반환 값을
지정하거나 사용 가능한 어트리뷰트를 제한하도록 구성한 다음, 사용된 방
식에 대한 어서션을 만들 수 있습니다:

>>> from unittest.mock import MagicMock
>>> thing = ProductionClass()
>>> thing.method = MagicMock(return_value=3)
>>> thing.method(3, 4, 5, key='value')
3
>>> thing.method.assert_called_with(3, 4, 5, key='value')

"side_effect"를 사용하면 모의 객체(mock)가 호출될 때 예외를 발생시키는
것을 포함하여 부작용(side effect)을 수행 할 수 있습니다:

>>> mock = Mock(side_effect=KeyError('foo'))
>>> mock()
Traceback (most recent call last):
 ...
KeyError: 'foo'

>>> values = {'a': 1, 'b': 2, 'c': 3}
>>> def side_effect(arg):
...     return values[arg]
...
>>> mock.side_effect = side_effect
>>> mock('a'), mock('b'), mock('c')
(1, 2, 3)
>>> mock.side_effect = [5, 4, 3, 2, 1]
>>> mock(), mock(), mock()
(5, 4, 3)

Mock은 여러 가지 방법으로 구성하고 동작을 제어 할 수 있습니다. 예를 들
어 *spec* 인자는 다른 객체에서 사양을 가져오도록 모의 객체를 구성합니
다. spec에 존재하지 않는 모의 객체의 어트리뷰트나 메서드에 액세스하려
고 시도하면 "AttributeError"로 실패합니다.

"patch()" 데코레이터 / 컨텍스트 관리자는 테스트 대상 모듈에서 클래스나
객체를 쉽게 모킹할 수 있도록 합니다. 지정한 객체는 테스트 중에 모의 객
체(또는 다른 객체)로 치환되고 테스트가 끝나면 복원됩니다:

   >>> from unittest.mock import patch
   >>> @patch('module.ClassName2')
   ... @patch('module.ClassName1')
   ... def test(MockClass1, MockClass2):
   ...     module.ClassName1()
   ...     module.ClassName2()
   ...     assert MockClass1 is module.ClassName1
   ...     assert MockClass2 is module.ClassName2
   ...     assert MockClass1.called
   ...     assert MockClass2.called
   ...
   >>> test()

참고:

  patch 데코레이터를 중첩할 때 모의 객체는 적용한 순서와 같은 순서로
  데코레이트 되는 함수로 전달됩니다 (데코레이터가 적용되는 일반적인 *
  파이썬* 순서). 이것은 아래에서 위로 감을 뜻하므로, 위의 예에서
  "module.ClassName1"에 대한 모의 객체가 먼저 전달됩니다."patch()"를
  사용할 때 조회되는 이름 공간에서 객체를 패치하는 것이 중요합니다. 이
  것은 일반적으로 간단하지만, 간략 지침은 패치할 곳을 읽으십시오.

데코레이터 "patch()"는 with 문에서 컨텍스트 관리자로 사용할 수도 있습
니다:

>>> with patch.object(ProductionClass, 'method', return_value=None) as mock_method:
...     thing = ProductionClass()
...     thing.method(1, 2, 3)
...
>>> mock_method.assert_called_once_with(1, 2, 3)

스코프 도중 딕셔너리에 값을 설정하고 테스트가 종료될 때 딕셔너리를 원
래 상태로 복원하기 위한 "patch.dict()"도 있습니다:

>>> foo = {'key': 'value'}
>>> original = foo.copy()
>>> with patch.dict(foo, {'newkey': 'newvalue'}, clear=True):
...     assert foo == {'newkey': 'newvalue'}
...
>>> assert foo == original

Mock은 파이썬 매직 메서드의 모킹을 지원합니다. 매직 메서드를 사용하는
가장 쉬운 방법은 "MagicMock" 클래스를 사용하는 것입니다. 다음과 같은
것을 할 수 있도록 합니다:

>>> mock = MagicMock()
>>> mock.__str__.return_value = 'foobarbaz'
>>> str(mock)
'foobarbaz'
>>> mock.__str__.assert_called_with()

Mock을 사용하면 함수(또는 다른 Mock 인스턴스)를 매직 메서드에 대입할
수 있고 적절하게 호출될 것입니다. "MagicMock" 클래스는 모든 매직 메서
드(아마도, 모든 유용한 메서드)가 미리 만들어져 있는 Mock 변형일 뿐입니
다.

다음은 평범한 Mock 클래스로 매직 메서드를 사용하는 예입니다:

>>> mock = Mock()
>>> mock.__str__ = Mock(return_value='wheeeeee')
>>> str(mock)
'wheeeeee'

테스트의 모의 객체가 대체하는 객체와 같은 api를 갖도록, 자동 사양를 사
용할 수 있습니다. 자동 사양은 패치 할 *autospec* 인자를 patch에 전달하
거나 "create_autospec()" 함수를 통해 수행할 수 있습니다. 자동 사양은
대체하는 객체와 같은 어트리뷰트와 메서드를 갖는 모의 객체를 만들고, 모
든 함수와 (생성자를 포함한) 메서드는 실제 객체와 같은 호출 서명을 갖습
니다.

이것은 모의 객체가 잘못 사용될 경우 프로덕션 코드와 같은 방식으로 실패
하도록 합니다:

>>> from unittest.mock import create_autospec
>>> def function(a, b, c):
...     pass
...
>>> mock_function = create_autospec(function, return_value='fishy')
>>> mock_function(1, 2, 3)
'fishy'
>>> mock_function.assert_called_once_with(1, 2, 3)
>>> mock_function('wrong arguments')
Traceback (most recent call last):
 ...
TypeError: <lambda>() takes exactly 3 arguments (1 given)

"create_autospec()"이 클래스에 사용되면 "__init__" 메서드의 서명을 복
사하고, 콜러블 객체에 사용되면 "__call__" 메서드의 서명을 복사합니다.


Mock 클래스
===========

"Mock"은 코드 전체에서 스텁과 테스트 이중화의 사용을 대체하기 위한 유
연한 모의 객체입니다. 모의 객체는 콜러블이고 어트리뷰트에 액세스할 때
새 모의 객체로 어트리뷰트를 만듭니다 [1]. 같은 어트리뷰트에 액세스하면
항상 같은 모의 객체를 반환합니다. 모의 객체는 사용 방법을 기록하여, 코
드가 모의 객체에 대해 수행한 작업에 대한 어서션을 만들 수 있도록 합니
다.

"MagicMock"은 "Mock"의 서브 클래스이며, 모든 매직 메서드가 미리 만들어
져 사용할 준비가 되어있습니다. 콜러블이 아닌 변형도 있어서, 콜러블이
아닌 객체를 모킹할 때 유용합니다: "NonCallableMock"과
"NonCallableMagicMock"

"patch()" 데코레이터를 사용하면 특정 모듈의 클래스를 "Mock" 객체로 쉽
게 대체 할 수 있습니다. 기본적으로 "patch()"는 "MagicMock"을 생성합니
다. "patch()"에 *new_callable* 인자를 사용하여 대체 "Mock" 클래스를 지
정할 수 있습니다.

class unittest.mock.Mock(spec=None, side_effect=None, return_value=DEFAULT, wraps=None, name=None, spec_set=None, unsafe=False, **kwargs)

   새로운 "Mock" 객체를 만듭니다. "Mock"은 Mock 객체의 동작을 지정하는
   몇 가지 선택적 인자를 취합니다:

   * *spec*: 문자열 리스트이거나 모의 객체의 사양으로 작동하는 기존 객
     체 (클래스나 인스턴스)일 수 있습니다. 객체를 전달하면 객체에 dir
     을 호출하여 문자열 리스트가 형성됩니다 (지원되지 않는 매직 어트리
     뷰트와 메서드는 제외합니다). 이 리스트에 없는 어트리뷰트에 액세스
     하면 "AttributeError"가 발생합니다.

     *spec*이 (문자열 리스트 대신에) 객체이면, "__class__"는 spec 객체
     의 클래스를 반환합니다. 이것은 모의 객체가 "isinstance()" 검사를
     통과할 수 있도록 합니다.

   * *spec_set*: *spec*의 더 엄격한 변형. 사용되면, *spec_set*으로 전
     달된 객체에 없는 모의 객체의 어트리뷰트를 *설정*하거나 얻으려고
     시도하면 "AttributeError"가 발생합니다.

   * *side_effect*: Mock이 호출될 때마다 호출되는 함수. "side_effect"
     어트리뷰트를 참조하십시오. 예외를 발생시키거나 반환 값을 동적으로
     변경하는 데 유용합니다. 함수는 모의 객체와 같은 인자로 호출되며,
     "DEFAULT"를 반환하지 않는 한, 이 함수의 반환 값이 반환 값으로 사
     용됩니다.

     또는 *side_effect*는 예외 클래스나 인스턴스일 수 있습니다. 이 경
     우 모의 객체가 호출될 때 그 예외가 발생합니다.

     *side_effect*가 이터러블이면 모의 객체에 대한 각 호출은 이터러블
     의 다음 값을 반환합니다.

     *side_effect*는 "None"으로 설정하여 지울 수 있습니다.

   * *return_value*: 모의 객체가 호출될 때 반환되는 값. 기본적으로 이
     것은 새로운 Mock입니다 (처음 액세스할 때 만들어집니다).
     "return_value" 어트리뷰트를 참조하십시오.

   * *unsafe*: 기본적으로 어트리뷰트가 *assert*나 *assret*로 시작하면
     "AttributeError"가 발생합니다. "unsafe=True"를 전달하면 이러한 어
     트리뷰트에 액세스 할 수 있습니다.

     버전 3.5에 추가.

   * *wraps*: 모의 객체가 감쌀 항목. *wraps*가 "None"이 아니면 Mock을
     호출할 때 래핑 된 객체로 호출이 전달됩니다 (실제 결과를 반환합니
     다). 모의 객체에 대한 어트리뷰트 액세스는 래핑 된 객체의 해당 어
     트리뷰트를 래핑하는 Mock 객체를 반환합니다 (따라서 존재하지 않는
     어트리뷰트에 액세스하려고 시도하면 "AttributeError"가 발생합니다
     ).

     모의 객체에 명시적으로 *return_value*가 설정되면 호출은 래핑 된
     객체로 전달되지 않고 대신 *return_value*가 반환됩니다.

   * *name*: 모의 객체에 이름이 있으면 모의 객체의 repr에 사용됩니다.
     디버깅에 유용할 수 있습니다. 이름은 자식 모의 객체로 전파됩니다.

   임의의 키워드 인자로 모의 객체를 호출할 수도 있습니다. 이것들은 모
   의 객체가 만들어진 후에 어트리뷰트를 설정하는 데 사용됩니다. 자세한
   내용은 "configure_mock()" 메서드를 참조하십시오.

   assert_called()

      모의 객체가 적어도 한 번 호출되었다고 어서트 합니다.

      >>> mock = Mock()
      >>> mock.method()
      <Mock name='mock.method()' id='...'>
      >>> mock.method.assert_called()

      버전 3.6에 추가.

   assert_called_once()

      모의 객체가 정확히 한 번 호출되었다고 어서트 합니다.

      >>> mock = Mock()
      >>> mock.method()
      <Mock name='mock.method()' id='...'>
      >>> mock.method.assert_called_once()
      >>> mock.method()
      <Mock name='mock.method()' id='...'>
      >>> mock.method.assert_called_once()
      Traceback (most recent call last):
      ...
      AssertionError: Expected 'method' to have been called once. Called 2 times.

      버전 3.6에 추가.

   assert_called_with(*args, **kwargs)

      이 메서드는 마지막 호출이 특정 방식으로 이루어졌음을 어서트하는
      편리한 방법입니다:

      >>> mock = Mock()
      >>> mock.method(1, 2, 3, test='wow')
      <Mock name='mock.method()' id='...'>
      >>> mock.method.assert_called_with(1, 2, 3, test='wow')

   assert_called_once_with(*args, **kwargs)

      모의 객체가 정확히 한 번 호출되었고 해당 호출이 지정된 인자로 이
      루어졌다고 어서트 합니다.

      >>> mock = Mock(return_value=None)
      >>> mock('foo', bar='baz')
      >>> mock.assert_called_once_with('foo', bar='baz')
      >>> mock('other', bar='values')
      >>> mock.assert_called_once_with('other', bar='values')
      Traceback (most recent call last):
        ...
      AssertionError: Expected 'mock' to be called once. Called 2 times.

   assert_any_call(*args, **kwargs)

      지정된 인자로 모의 객체가 호출되었다고 어서트 합니다.

      호출이 가장 최근 호출일 때만 통과하는 "assert_called_with()"와
      "assert_called_once_with()", 그리고 "assert_called_once_with()"
      의 경우 유일한 호출이어야 하는 것과 달리 모의 객체가 호출된 적이
      *있으면* 어서트가 통과합니다.

      >>> mock = Mock(return_value=None)
      >>> mock(1, 2, arg='thing')
      >>> mock('some', 'thing', 'else')
      >>> mock.assert_any_call(1, 2, arg='thing')

   assert_has_calls(calls, any_order=False)

      지정된 호출로 모의 객체가 호출되었다고 어서트 합니다. calls에 대
      해 "mock_calls" 리스트를 검사합니다.

      *any_order*가 거짓이면 호출은 순차적이어야 합니다. 지정된 호출
      전후에 추가 호출이 있을 수 있습니다.

      *any_order*가 참이면 호출 순서는 상관없지만, 모두 "mock_calls"에
      나타나야 합니다.

      >>> mock = Mock(return_value=None)
      >>> mock(1)
      >>> mock(2)
      >>> mock(3)
      >>> mock(4)
      >>> calls = [call(2), call(3)]
      >>> mock.assert_has_calls(calls)
      >>> calls = [call(4), call(2), call(3)]
      >>> mock.assert_has_calls(calls, any_order=True)

   assert_not_called()

      모의 객체가 호출되지 않았다고 어서트 합니다.

      >>> m = Mock()
      >>> m.hello.assert_not_called()
      >>> obj = m.hello()
      >>> m.hello.assert_not_called()
      Traceback (most recent call last):
        ...
      AssertionError: Expected 'hello' to not have been called. Called 1 times.

      버전 3.5에 추가.

   reset_mock(*, return_value=False, side_effect=False)

      reset_mock 메서드는 모의 객체의 모든 호출 어트리뷰트를 재설정합
      니다:

      >>> mock = Mock(return_value=None)
      >>> mock('hello')
      >>> mock.called
      True
      >>> mock.reset_mock()
      >>> mock.called
      False

      버전 3.6에서 변경: reset_mock 함수에 두 개의 키워드 전용 인자를
      추가했습니다.

      같은 객체를 재사용하는 일련의 어서션을 만들려는 경우에 유용할 수
      있습니다. "reset_mock()"은 기본적으로 정규 대입을 사용하여 설정
      한 반환 값, "side_effect" 또는 모든 자식 어트리뷰트를 지우지 *않
      음*에 유의하십시오. *return_value*나 "side_effect"를 재설정하려
      면, 해당 매개 변수를 "True"로 전달하십시오. 자식 모의 객체와 반
      환 값 모의 객체(있다면)도 재설정됩니다.

      참고:

        *return_value*와 "side_effect"는 키워드 전용 인자입니다.

   mock_add_spec(spec, spec_set=False)

      모의 객체에 사양을 추가합니다. *spec*은 객체이거나 문자열 리스트
      일 수 있습니다. *spec*의 어트리뷰트 만 모의 객체에서 어트리뷰트
      로 꺼낼 수 있습니다.

      *spec_set*이 참이면 스펙에 있는 어트리뷰트 만 설정할 수 있습니다
      .

   attach_mock(mock, attribute)

      이름과 부모를 치환해서, 이것의 어트리뷰트(attribute)로 모의 객체
      (mock)를 연결합니다. 연결된 모의 객체에 대한 호출은 이것의
      "method_calls"와 "mock_calls" 어트리뷰트에 기록됩니다.

   configure_mock(**kwargs)

      키워드 인자를 통해 모의 객체의 어트리뷰트를 설정합니다.

      표준 점 표기법과 메서드 호출에서 딕셔너리 언 패킹을 사용해서 자
      식 모의 객체에 어트리뷰트와 반환 값 및 부작용을 설정할 수 있습니
      다:

      >>> mock = Mock()
      >>> attrs = {'method.return_value': 3, 'other.side_effect': KeyError}
      >>> mock.configure_mock(**attrs)
      >>> mock.method()
      3
      >>> mock.other()
      Traceback (most recent call last):
        ...
      KeyError

      모의 객체에 대한 생성자 호출에서 같은 것을 할 수 있습니다:

      >>> attrs = {'method.return_value': 3, 'other.side_effect': KeyError}
      >>> mock = Mock(some_attribute='eggs', **attrs)
      >>> mock.some_attribute
      'eggs'
      >>> mock.method()
      3
      >>> mock.other()
      Traceback (most recent call last):
        ...
      KeyError

      "configure_mock()"은 모의 객체를 만든 후에 구성을 더 쉽게 할 수
      있도록 하기 위해 존재합니다.

   __dir__()

      "Mock" 객체는 "dir(some_mock)"의 결과를 유용한 결과로 제한합니다
      . *spec*이 있는 모의 객체에서 이것은 모의 객체에 허용되는 모든
      어트리뷰트를 포함합니다.

      이 필터링이 하는 일과 해제 방법에 대해서는 "FILTER_DIR"을 참조하
      십시오.

   _get_child_mock(**kw)

      어트리뷰트와 반환 값에 대한 자식 모의 객체를 만듭니다. 기본적으
      로 자식 모의 객체는 부모와 같은 형입니다. Mock의 서브 클래스는
      자식 모의 객체가 만들어지는 방법을 사용자 정의하기 위해 이를 재
      정의할 수 있습니다.

      콜러블이 아닌 모의 객체의 경우 (사용자 정의 서브 클래스 대신) 콜
      러블 변형이 사용됩니다.

   called

      모의 객체가 호출되었는지를 나타내는 불리언:

      >>> mock = Mock(return_value=None)
      >>> mock.called
      False
      >>> mock()
      >>> mock.called
      True

   call_count

      모의 객체가 몇 번이나 호출되었는지를 알려주는 정수:

      >>> mock = Mock(return_value=None)
      >>> mock.call_count
      0
      >>> mock()
      >>> mock()
      >>> mock.call_count
      2

   return_value

      모의 객체를 호출할 때 반환되는 값을 구성하려면 이것을 설정하십시
      오:

      >>> mock = Mock()
      >>> mock.return_value = 'fish'
      >>> mock()
      'fish'

      기본 반환 값은 모의 객체이며 일반적인 방식으로 구성할 수 있습니
      다:

      >>> mock = Mock()
      >>> mock.return_value.attribute = sentinel.Attribute
      >>> mock.return_value()
      <Mock name='mock()()' id='...'>
      >>> mock.return_value.assert_called_with()

      생성자에서 "return_value"를 설정할 수도 있습니다:

      >>> mock = Mock(return_value=3)
      >>> mock.return_value
      3
      >>> mock()
      3

   side_effect

      이것은 모의 객체가 호출될 때 호출되는 함수, 이터러블 또는 발생시
      킬 예외(클래스나 인스턴스)일 수 있습니다.

      함수를 전달하면 모의 객체와 같은 인자로 호출되며 함수가
      "DEFAULT" 싱글톤을 반환하지 않는 한 모의 객체에 대한 호출은 함수
      가 반환하는 것을 반환합니다. 함수가 "DEFAULT"를 반환하면 모의 객
      체는 ("return_value"에서) 정상값을 반환합니다.

      이터러블을 전달하면, 모든 호출에서 값을 산출해야 하는 이터레이터
      를 얻는 데 사용됩니다. 이 값은 발생시킬 예외 인스턴스나 모의 객
      체 호출에서 반환될 값일 수 있습니다 ("DEFAULT" 처리는 함수 경우
      와 같습니다).

      (API의 예외 처리를 테스트하기 위해) 예외를 발생시키는 모의 객체
      예:

      >>> mock = Mock()
      >>> mock.side_effect = Exception('Boom!')
      >>> mock()
      Traceback (most recent call last):
        ...
      Exception: Boom!

      "side_effect"를 사용하여 일련의 값을 반환하기:

      >>> mock = Mock()
      >>> mock.side_effect = [3, 2, 1]
      >>> mock(), mock(), mock()
      (3, 2, 1)

      콜러블 사용하기:

      >>> mock = Mock(return_value=3)
      >>> def side_effect(*args, **kwargs):
      ...     return DEFAULT
      ...
      >>> mock.side_effect = side_effect
      >>> mock()
      3

      생성자에서 "side_effect"를 설정할 수 있습니다. 다음은 모의 객체
      가 호출된 값에 1을 더해서 반환하는 예입니다:

      >>> side_effect = lambda value: value + 1
      >>> mock = Mock(side_effect=side_effect)
      >>> mock(3)
      4
      >>> mock(-8)
      -7

      "side_effect"를 "None"으로 설정하면 지워집니다:

      >>> m = Mock(side_effect=KeyError, return_value=3)
      >>> m()
      Traceback (most recent call last):
       ...
      KeyError
      >>> m.side_effect = None
      >>> m()
      3

   call_args

      이것은 "None"(모의 객체가 호출되지 않았을 때)이거나 모의 객체가
      마지막으로 호출된 인자입니다. 이것은 튜플 형태입니다: "args" 프
      로퍼티를 통해 액세스 할 수도 있는 첫 번째 멤버는 모의 객체를 호
      출한 순서 있는 인자(또는 빈 튜플)이며 "kwargs" 프로퍼티를 통해
      액세스 할 수도 있는 두 번째 멤버는 모든 키워드 인자(또는 빈 딕셔
      너리)입니다.

      >>> mock = Mock(return_value=None)
      >>> print(mock.call_args)
      None
      >>> mock()
      >>> mock.call_args
      call()
      >>> mock.call_args == ()
      True
      >>> mock(3, 4)
      >>> mock.call_args
      call(3, 4)
      >>> mock.call_args == ((3, 4),)
      True
      >>> mock.call_args.args
      (3, 4)
      >>> mock.call_args.kwargs
      {}
      >>> mock(3, 4, 5, key='fish', next='w00t!')
      >>> mock.call_args
      call(3, 4, 5, key='fish', next='w00t!')
      >>> mock.call_args.args
      (3, 4, 5)
      >>> mock.call_args.kwargs
      {'key': 'fish', 'next': 'w00t!'}

      "call_args_list", "method_calls" 및 "mock_calls" 리스트의 멤버와
      함께 "call_args"는 "call" 객체입니다. 이들은 튜플이므로, 개별 인
      자를 얻고 더 복잡한 어서션을 하기 위해 언팩할 수 있습니다. call
      튜플을 참조하십시오.

      버전 3.8에서 변경: "args"와 "kwargs" 프로퍼티를 추가했습니다.

   call_args_list

      이것은 모의 객체에 대한 모든 호출을 순서대로 나열한 리스트입니다
      (따라서 리스트의 길이는 호출된 횟수입니다). 호출이 있기 전에는
      빈 리스트입니다. "call" 객체는 "call_args_list"와 비교할 호출 리
      스트를 편리하게 구성하는 데 사용할 수 있습니다.

      >>> mock = Mock(return_value=None)
      >>> mock()
      >>> mock(3, 4)
      >>> mock(key='fish', next='w00t!')
      >>> mock.call_args_list
      [call(), call(3, 4), call(key='fish', next='w00t!')]
      >>> expected = [(), ((3, 4),), ({'key': 'fish', 'next': 'w00t!'},)]
      >>> mock.call_args_list == expected
      True

      "call_args_list"의 멤버는 "call" 객체입니다. 이들은 개별 인자를
      얻기 위해 튜플로서 언팩될 수 있습니다. call 튜플을 참조하십시오.

   method_calls

      자신에 대한 호출 추적뿐만 아니라, 모의 객체는 메서드와 어트리뷰
      트, 그리고 *그들의* 메서드와 어트리뷰트에 대한 호출도 추적합니다
      :

      >>> mock = Mock()
      >>> mock.method()
      <Mock name='mock.method()' id='...'>
      >>> mock.property.method.attribute()
      <Mock name='mock.property.method.attribute()' id='...'>
      >>> mock.method_calls
      [call.method(), call.property.method.attribute()]

      "method_calls"의 멤버는 "call" 객체입니다. 이들은 개별 인자를 얻
      기 위해 튜플로서 언팩될 수 있습니다. call 튜플을 참조하십시오.

   mock_calls

      "mock_calls"는 모의 객체, 그것의 메서드, 매직 메서드 *및* 반환
      값 모의 객체에 대한 *모든* 호출을 기록합니다.

      >>> mock = MagicMock()
      >>> result = mock(1, 2, 3)
      >>> mock.first(a=3)
      <MagicMock name='mock.first()' id='...'>
      >>> mock.second()
      <MagicMock name='mock.second()' id='...'>
      >>> int(mock)
      1
      >>> result(1)
      <MagicMock name='mock()()' id='...'>
      >>> expected = [call(1, 2, 3), call.first(a=3), call.second(),
      ... call.__int__(), call()(1)]
      >>> mock.mock_calls == expected
      True

      "mock_calls"의 멤버는 "call" 객체입니다. 이들은 개별 인자를 얻기
      위해 튜플로서 언팩될 수 있습니다. call 튜플을 참조하십시오.

      참고:

        "mock_calls"가 기록되는 방식은 중첩된 호출이 수행될 때 상위 호
        출의 매개 변수가 기록되지 않아서 항상 같다고 비교됨을 뜻합니다
        .:

        >>> mock = MagicMock()
        >>> mock.top(a=3).bottom()
        <MagicMock name='mock.top().bottom()' id='...'>
        >>> mock.mock_calls
        [call.top(a=3), call.top().bottom()]
        >>> mock.mock_calls[-1] == call.top(a=-1).bottom()
        True

   __class__

      일반적으로 객체의 "__class__" 어트리뷰트는 해당 형을 반환합니다.
      "spec"이 있는 모의 객체의 경우, "__class__"는 대신 spec 클래스를
      반환합니다. 이를 통해 모의 객체는 다음과 같이 대체 / 가장하는 객
      체에 대한 "isinstance()" 테스트를 통과할 수 있습니다:

      >>> mock = Mock(spec=3)
      >>> isinstance(mock, int)
      True

      "__class__"는 대입할 수 있습니다. 이를 통해 spec을 사용하지 않고
      도 모의 객체가 "isinstance()" 검사를 통과할 수 있습니다.:

      >>> mock = Mock()
      >>> mock.__class__ = dict
      >>> isinstance(mock, dict)
      True

class unittest.mock.NonCallableMock(spec=None, wraps=None, name=None, spec_set=None, **kwargs)

   콜러블이 아닌 "Mock" 버전. 생성자 매개 변수는 "Mock"과 같은 의미를
   가지며, 콜러블이 아닌 모의 객체에서 의미가 없는 *return_value*와
   *side_effect*는 예외입니다.

클래스 나 인스턴스를 "spec"이나 "spec_set"으로 사용하는 모의 객체는
"isinstance()" 테스트를 통과할 수 있습니다:

>>> mock = Mock(spec=SomeClass)
>>> isinstance(mock, SomeClass)
True
>>> mock = Mock(spec_set=SomeClass())
>>> isinstance(mock, SomeClass)
True

"Mock" 클래스는 매직 메서드 모킹을 지원합니다. 자세한 내용은 매직 메서
드를 참조하십시오.

모의 객체 클래스와 "patch()" 데코레이터는 모두 구성을 위해 임의의 키워
드 인자를 취합니다. "patch()" 데코레이터의 경우 키워드는 만들어지는 모
의 객체의 생성자로 전달됩니다. 키워드 인자는 모의 객체의 어트리뷰트를
구성하기 위한 것입니다.:

>>> m = MagicMock(attribute=3, other='fish')
>>> m.attribute
3
>>> m.other
'fish'

자식 모의 객체의 반환 값과 부작용은 점 표기법을 사용하여 같은 방식으로
설정할 수 있습니다. 호출에서 점으로 구분된 이름을 직접 사용할 수 없어
서 딕셔너리를 만들고 "**"를 사용하여 언팩해야 합니다:

>>> attrs = {'method.return_value': 3, 'other.side_effect': KeyError}
>>> mock = Mock(some_attribute='eggs', **attrs)
>>> mock.some_attribute
'eggs'
>>> mock.method()
3
>>> mock.other()
Traceback (most recent call last):
  ...
KeyError

*spec*(또는 *spec_set*)으로 만들어진 콜러블 모의 객체는 호출을 모의 객
체와 일치시킬 때 사양 객체의 서명을 검사합니다. 따라서, 위치나 이름으
로 전달되었는지와 관계없이 실제 호출의 인자와 일치할 수 있습니다:

   >>> def f(a, b, c): pass
   ...
   >>> mock = Mock(spec=f)
   >>> mock(1, 2, c=3)
   <Mock name='mock()' id='140161580456576'>
   >>> mock.assert_called_with(1, 2, 3)
   >>> mock.assert_called_with(a=1, b=2, c=3)

이것은 "assert_called_with()", "assert_called_once_with()",
"assert_has_calls()" 및 "assert_any_call()"에 적용됩니다. 자동 사양할
때, 모의 객체의 메서드 호출에도 적용됩니다.

   버전 3.4에서 변경: spec 되거나 자동 사양된 모의 객체에 대한 서명 검
   사를 추가했습니다.

class unittest.mock.PropertyMock(*args, **kwargs)

   클래스에서 프로퍼티나 다른 디스크립터로 사용하기 위한 모의 객체.
   "PropertyMock"은 "__get__()"과 "__set__()" 메서드를 제공하므로 꺼낼
   때 반환 값을 지정할 수 있습니다.

   객체에서 "PropertyMock" 인스턴스를 가져오면 인자 없이 모의 객체를
   호출합니다. 설정하면 설정되는 값으로 모의 객체를 호출합니다.

      >>> class Foo:
      ...     @property
      ...     def foo(self):
      ...         return 'something'
      ...     @foo.setter
      ...     def foo(self, value):
      ...         pass
      ...
      >>> with patch('__main__.Foo.foo', new_callable=PropertyMock) as mock_foo:
      ...     mock_foo.return_value = 'mockity-mock'
      ...     this_foo = Foo()
      ...     print(this_foo.foo)
      ...     this_foo.foo = 6
      ...
      mockity-mock
      >>> mock_foo.mock_calls
      [call(), call(6)]

모의 객체 어트리뷰트가 저장되는 방식으로 인해 "PropertyMock"을 모의 객
체에 직접 연결할 수 없습니다. 대신 모의 객체의 형 객체에 연결할 수 있
습니다:

   >>> m = MagicMock()
   >>> p = PropertyMock(return_value=3)
   >>> type(m).foo = p
   >>> m.foo
   3
   >>> p.assert_called_once_with()

class unittest.mock.AsyncMock(spec=None, side_effect=None, return_value=DEFAULT, wraps=None, name=None, spec_set=None, unsafe=False, **kwargs)

   An asynchronous version of "Mock". The "AsyncMock" object will
   behave so the object is recognized as an async function, and the
   result of a call is an awaitable.

   >>> mock = AsyncMock()
   >>> asyncio.iscoroutinefunction(mock)
   True
   >>> inspect.isawaitable(mock())  
   True

   "mock()"의 결과는 어웨이트 한 후 "side_effect"나 "return_value"를
   제공하는 비동기 함수입니다:

   * "side_effect"가 함수이면, 비동기 함수는 해당 함수의 결과를 반환합
     니다,

   * "side_effect"가 예외이면, 비동기 함수는 예외를 발생시킵니다,

   * "side_effect"가 이터러블이면, 비동기 함수는 이터러블의 다음 값을
     반환하지만, 결과 시퀀스가 소진되면 "StopAsyncIteration"이 즉시 발
     생합니다,

   * "side_effect"가 정의되지 않으면, 비동기 함수는 "return_value"에
     의해 정의된 값을 반환하므로, 기본적으로 비동기 함수는 새
     "AsyncMock" 객체를 반환합니다.

   "Mock"이나 "MagicMock"의 *spec*을 비동기 함수로 설정하면 호출 후에
   코루틴 객체가 반환됩니다.

   >>> async def async_func(): pass
   ...
   >>> mock = MagicMock(async_func)
   >>> mock
   <MagicMock spec='function' id='...'>
   >>> mock()  
   <coroutine object AsyncMockMixin._mock_call at ...>

   "Mock", "MagicMock" 또는 "AsyncMock"의 *spec*을 비동기와 동기 함수
   가 있는 클래스로 설정하면 동기 함수를 자동으로 감지하고 그들을
   "MagicMock"(부모 모의 객체가 "AsyncMock"이나 "MagicMock"일 때)이나
   "Mock"(부모 모의 객체가 "Mock"일 때)으로 설정합니다. 모든 비동기 함
   수는 "AsyncMock"이 됩니다.

   >>> class ExampleClass:
   ...     def sync_foo():
   ...         pass
   ...     async def async_foo():
   ...         pass
   ...
   >>> a_mock = AsyncMock(ExampleClass)
   >>> a_mock.sync_foo
   <MagicMock name='mock.sync_foo' id='...'>
   >>> a_mock.async_foo
   <AsyncMock name='mock.async_foo' id='...'>
   >>> mock = Mock(ExampleClass)
   >>> mock.sync_foo
   <Mock name='mock.sync_foo' id='...'>
   >>> mock.async_foo
   <AsyncMock name='mock.async_foo' id='...'>

   버전 3.8에 추가.

   assert_awaited()

      모의 객체가 적어도 한 번 어웨이트 되었다고 어서트 합니다. 이것은
      호출된 객체와 별개임에 유의하십시오, "await" 키워드를 반드시 사
      용해야 합니다:

      >>> mock = AsyncMock()
      >>> async def main(coroutine_mock):
      ...     await coroutine_mock
      ...
      >>> coroutine_mock = mock()
      >>> mock.called
      True
      >>> mock.assert_awaited()
      Traceback (most recent call last):
      ...
      AssertionError: Expected mock to have been awaited.
      >>> asyncio.run(main(coroutine_mock))
      >>> mock.assert_awaited()

   assert_awaited_once()

      모의 객체가 정확히 한 번 어웨이트 되었다고 어서트 합니다.

      >>> mock = AsyncMock()
      >>> async def main():
      ...     await mock()
      ...
      >>> asyncio.run(main())
      >>> mock.assert_awaited_once()
      >>> asyncio.run(main())
      >>> mock.method.assert_awaited_once()
      Traceback (most recent call last):
      ...
      AssertionError: Expected mock to have been awaited once. Awaited 2 times.

   assert_awaited_with(*args, **kwargs)

      마지막 어웨이트가 지정된 인자로 이루어졌다고 어서트 합니다.

      >>> mock = AsyncMock()
      >>> async def main(*args, **kwargs):
      ...     await mock(*args, **kwargs)
      ...
      >>> asyncio.run(main('foo', bar='bar'))
      >>> mock.assert_awaited_with('foo', bar='bar')
      >>> mock.assert_awaited_with('other')
      Traceback (most recent call last):
      ...
      AssertionError: expected call not found.
      Expected: mock('other')
      Actual: mock('foo', bar='bar')

   assert_awaited_once_with(*args, **kwargs)

      모의 객체가 정확히 한 번, 지정된 인자로 어웨이트 되었다고 어서트
      합니다.

      >>> mock = AsyncMock()
      >>> async def main(*args, **kwargs):
      ...     await mock(*args, **kwargs)
      ...
      >>> asyncio.run(main('foo', bar='bar'))
      >>> mock.assert_awaited_once_with('foo', bar='bar')
      >>> asyncio.run(main('foo', bar='bar'))
      >>> mock.assert_awaited_once_with('foo', bar='bar')
      Traceback (most recent call last):
      ...
      AssertionError: Expected mock to have been awaited once. Awaited 2 times.

   assert_any_await(*args, **kwargs)

      지정된 인자로 모의 객체가 어웨이트된 적이 있다고 어서트 합니다.

      >>> mock = AsyncMock()
      >>> async def main(*args, **kwargs):
      ...     await mock(*args, **kwargs)
      ...
      >>> asyncio.run(main('foo', bar='bar'))
      >>> asyncio.run(main('hello'))
      >>> mock.assert_any_await('foo', bar='bar')
      >>> mock.assert_any_await('other')
      Traceback (most recent call last):
      ...
      AssertionError: mock('other') await not found

   assert_has_awaits(calls, any_order=False)

      지정된 호출로 모의 객체가 어웨이트 되었다고 어서트 합니다. 어웨
      이트에 대해 "await_args_list" 리스트가 검사됩니다.

      *any_order*가 거짓이면 어웨이트는 순차적이어야 합니다. 지정된 어
      웨이트 전이나 후에 추가 호출이 있을 수 있습니다.

      *any_order*가 참이면 어웨이트 순서와 관계없이 모두
      "await_args_list"에 나타나야 합니다.

      >>> mock = AsyncMock()
      >>> async def main(*args, **kwargs):
      ...     await mock(*args, **kwargs)
      ...
      >>> calls = [call("foo"), call("bar")]
      >>> mock.assert_has_awaits(calls)
      Traceback (most recent call last):
      ...
      AssertionError: Awaits not found.
      Expected: [call('foo'), call('bar')]
      Actual: []
      >>> asyncio.run(main('foo'))
      >>> asyncio.run(main('bar'))
      >>> mock.assert_has_awaits(calls)

   assert_not_awaited()

      모의 객체가 어웨이트 된 적이 없다고 어서트 합니다.

      >>> mock = AsyncMock()
      >>> mock.assert_not_awaited()

   reset_mock(*args, **kwargs)

      "Mock.reset_mock()"을 참조하십시오. 또한 "await_count"를 0으로,
      "await_args"를 None으로 설정하고, "await_args_list"를 지웁니다.

   await_count

      모의 객체가 몇 번 어웨이트 되었는지 추적하는 정수.

      >>> mock = AsyncMock()
      >>> async def main():
      ...     await mock()
      ...
      >>> asyncio.run(main())
      >>> mock.await_count
      1
      >>> asyncio.run(main())
      >>> mock.await_count
      2

   await_args

      이것은 "None"(모의 객체가 어웨이트 되지 않았을 때)이거나 모의 객
      체가 마지막으로 어웨이트 된 인자입니다. "Mock.call_args"와 같게
      기능합니다.

      >>> mock = AsyncMock()
      >>> async def main(*args):
      ...     await mock(*args)
      ...
      >>> mock.await_args
      >>> asyncio.run(main('foo'))
      >>> mock.await_args
      call('foo')
      >>> asyncio.run(main('bar'))
      >>> mock.await_args
      call('bar')

   await_args_list

      이것은 모의 객체에 대한 모든 어웨이트를 순서대로 나열한 리스트입
      니다 (따라서 리스트의 길이는 어웨이트 한 횟수입니다). 어웨이트
      전에는 빈 리스트입니다.

      >>> mock = AsyncMock()
      >>> async def main(*args):
      ...     await mock(*args)
      ...
      >>> mock.await_args_list
      []
      >>> asyncio.run(main('foo'))
      >>> mock.await_args_list
      [call('foo')]
      >>> asyncio.run(main('bar'))
      >>> mock.await_args_list
      [call('foo'), call('bar')]


호출
----

모의 객체는 콜러블입니다. 호출은 "return_value" 어트리뷰트로 설정된 값
을 반환합니다. 기본 반환 값은 새로운 Mock 객체입니다; (명시적으로나
Mock을 호출하여) 반환 값에 처음으로 액세스할 때 만들어지지만 - 저장되
고 매번 같은 값이 반환됩니다.

객체에 대한 호출은 "call_args"와 "call_args_list" 같은 어트리뷰트로 기
록됩니다.

"side_effect"가 설정되면 호출이 기록된 후에 호출되므로, "side_effect"
에서 예외가 발생해도 호출은 여전히 기록됩니다.

호출될 때 모의 객체가 예외를 발생시키는 가장 간단한 방법은
"side_effect"를 예외 클래스나 인스턴스로 만드는 것입니다:

>>> m = MagicMock(side_effect=IndexError)
>>> m(1, 2, 3)
Traceback (most recent call last):
  ...
IndexError
>>> m.mock_calls
[call(1, 2, 3)]
>>> m.side_effect = KeyError('Bang!')
>>> m('two', 'three', 'four')
Traceback (most recent call last):
  ...
KeyError: 'Bang!'
>>> m.mock_calls
[call(1, 2, 3), call('two', 'three', 'four')]

"side_effect"가 함수면 해당 함수가 반환하는 것이 모의 객체에 대한 호출
이 반환하는 것입니다. "side_effect" 함수는 모의 객체와 같은 인자로 호
출됩니다. 이를 통해 입력에 따라 호출의 반환 값을 동적으로 변경할 수 있
습니다:

>>> def side_effect(value):
...     return value + 1
...
>>> m = MagicMock(side_effect=side_effect)
>>> m(1)
2
>>> m(2)
3
>>> m.mock_calls
[call(1), call(2)]

모의 객체가 여전히 기본 반환 값(새로운 모의 객체)을, 또는 설정된 반환
값을, 반환하도록 하려면 두 가지 방법이 있습니다. "side_effect" 내부에
서 "mock.return_value"를 반환하거나 "DEFAULT"를 반환하십시오:

>>> m = MagicMock()
>>> def side_effect(*args, **kwargs):
...     return m.return_value
...
>>> m.side_effect = side_effect
>>> m.return_value = 3
>>> m()
3
>>> def side_effect(*args, **kwargs):
...     return DEFAULT
...
>>> m.side_effect = side_effect
>>> m()
3

"side_effect"를 제거하고 기본 동작으로 돌아가려면, "side_effect"를
"None"으로 설정하십시오:

>>> m = MagicMock(return_value=6)
>>> def side_effect(*args, **kwargs):
...     return 3
...
>>> m.side_effect = side_effect
>>> m()
3
>>> m.side_effect = None
>>> m()
6

"side_effect"는 이터러블 객체일 수도 있습니다. 모의 객체에 대한 반복
호출은 이터러블에서 값을 반환합니다 (이터러블이 소진되고
"StopIteration"이 발생할 때까지):

>>> m = MagicMock(side_effect=[1, 2, 3])
>>> m()
1
>>> m()
2
>>> m()
3
>>> m()
Traceback (most recent call last):
  ...
StopIteration

이터러블의 멤버가 예외이면 반환되는 대신 예외를 발생시킵니다:

   >>> iterable = (33, ValueError, 66)
   >>> m = MagicMock(side_effect=iterable)
   >>> m()
   33
   >>> m()
   Traceback (most recent call last):
    ...
   ValueError
   >>> m()
   66


어트리뷰트 삭제
---------------

모의 객체는 요청 시 어트리뷰트를 만듭니다. 이를 통해 모든 형의 객체인
것처럼 가장할 수 있습니다.

모의 객체가 "hasattr()" 호출에 대해 "False"를 반환하거나, 어트리뷰트를
가져올 때 "AttributeError"를 발생시키길 원할 수 있습니다. 모의 객체에
"spec"으로 객체를 제공하여 그렇게 할 수 있지만, 항상 편리하지는 않습니
다.

어트리뷰트를 삭제하여 어트리뷰트를 "차단"합니다. 일단 삭제되면, 어트리
뷰트에 액세스할 때 "AttributeError"가 발생합니다.

>>> mock = MagicMock()
>>> hasattr(mock, 'm')
True
>>> del mock.m
>>> hasattr(mock, 'm')
False
>>> del mock.f
>>> mock.f
Traceback (most recent call last):
    ...
AttributeError: f


모의 객체 이름과 이름 어트리뷰트
--------------------------------

"name"은 "Mock" 생성자에 대한 인자이므로, 모의 객체가 "name" 어트리뷰
트를 가지려면 생성 시 전달할 수 없습니다. 두 가지 대안이 있습니다. 한
가지 옵션은 "configure_mock()"을 사용하는 것입니다:

   >>> mock = MagicMock()
   >>> mock.configure_mock(name='my_name')
   >>> mock.name
   'my_name'

더 간단한 옵션은 모의 객체를 만든 후 단순히 "name" 어트리뷰트를 설정하
는 것입니다:

   >>> mock = MagicMock()
   >>> mock.name = "foo"


모의 객체를 어트리뷰트로 연결하기
---------------------------------

모의 객체를 다른 모의 객체의 어트리뷰트로 (또는 반환 값으로) 연결하면
그 모의 객체의 "자식"이 됩니다. 자식에 대한 호출은 부모의
"method_calls"와 "mock_calls" 어트리뷰트에 기록됩니다. 이는 자식 모의
객체를 구성한 다음 부모에 연결하는 데 유용합니다. 또는 자식들에 대한
모든 호출을 기록하는 부모에 여러 모의 객체를 연결하고 모의 객체 간의
호출 순서에 대한 어서션을 하는 데 유용합니다:

>>> parent = MagicMock()
>>> child1 = MagicMock(return_value=None)
>>> child2 = MagicMock(return_value=None)
>>> parent.child1 = child1
>>> parent.child2 = child2
>>> child1(1)
>>> child2(2)
>>> parent.mock_calls
[call.child1(1), call.child2(2)]

이에 대한 예외는 모의 객체에 이름이 있는 경우입니다. 어떤 이유로든 원
하지 않을 때 "부모가 되는 것(parenting)"을 방지 할 수 있습니다.

>>> mock = MagicMock()
>>> not_a_child = MagicMock(name='not-a-child')
>>> mock.attribute = not_a_child
>>> mock.attribute()
<MagicMock name='not-a-child()' id='...'>
>>> mock.mock_calls
[]

"patch()"가 만든 모의 객체에는 자동으로 이름이 지정됩니다. 부모에게 이
름을 가진 모의 객체를 연결하려면 "attach_mock()" 메서드를 사용하십시오
:

   >>> thing1 = object()
   >>> thing2 = object()
   >>> parent = MagicMock()
   >>> with patch('__main__.thing1', return_value=None) as child1:
   ...     with patch('__main__.thing2', return_value=None) as child2:
   ...         parent.attach_mock(child1, 'child1')
   ...         parent.attach_mock(child2, 'child2')
   ...         child1('one')
   ...         child2('two')
   ...
   >>> parent.mock_calls
   [call.child1('one'), call.child2('two')]

[1] 유일한 예외는 매직 메서드와 어트리뷰트(앞뒤에 이중 밑줄을 가진 것)
    입니다. Mock은 이것을 만들지 않고 대신 "AttributeError"를 발생시킵
    니다. 이는 인터프리터가 종종 묵시적으로 이러한 메서드를 요청하고,
    매직 메서드를 기대할 때 새 Mock 객체를 얻으면 *매우* 혼동되기 때문
    입니다. 매직 메서드 지원이 필요하면 매직 메서드를 참조하십시오.


패처
====

patch 데코레이터는 데코레이트 하는 함수의 스코프 내에서만 객체를 패치
하는 데 사용됩니다. 예외가 발생하더라도 자동으로 패치 해제를 처리합니
다. 이러한 함수는 모두 with 문에서 사용될 수 있고, 클래스 데코레이터로
도 사용할 수 있습니다.


patch
-----

참고:

  "patch()" is straightforward to use. The key is to do the patching
  in the right namespace. See the section where to patch.

unittest.mock.patch(target, new=DEFAULT, spec=None, create=False, spec_set=None, autospec=None, new_callable=None, **kwargs)

   "patch()"는 함수 데코레이터, 클래스 데코레이터 또는 컨텍스트 관리자
   역할을 합니다. 함수 본문이나 with 문 내부에서, *target*은 *new* 객
   체로 패치됩니다. 함수/with 문이 종료될 때 패치가 복구됩니다.

   *new*가 생략되면, 대상(target)은 패치된 객체가 비동기 함수이면
   "AsyncMock"으로, 그렇지 않으면 "MagicMock"으로 치환됩니다.
   "patch()"가 데코레이터로 사용되고 *new*가 생략되면, 만들어진 모의
   객체는 데코레이트 되는 함수에 대한 추가 인자로 전달됩니다.
   "patch()"가 컨텍스트 관리자로 사용되면 만들어진 모의 객체는 컨텍스
   트 관리자에 의해 반환됩니다.

   *target*은 "'package.module.ClassName'" 형식의 문자열이어야 합니다.
   *target*이 임포트되고 지정된 객체를 *new* 객체로 치환하므로,
   "patch()"를 호출하는 환경에서 *target*을 임포트 할 수 있어야 합니다
   . 데코레이트 하는 시간이 아니라 데코레이트 된 함수가 실행될 때 대상
   (target)을 임포트 합니다.

   patch가 여러분을 위해 만든다면 *spec*과 *spec_set* 키워드 인자는
   "MagicMock"으로 전달됩니다.

   또한 "spec=True"나 "spec_set=True"를 전달하면, patch는 모킹되는 객
   체를 spec/spec_set 객체로 전달합니다.

   *new_callable*을 사용하면 *new* 객체를 만들기 위해 호출될 다른 클래
   스나 콜러블 객체를 지정할 수 있습니다. 기본적으로 "AsyncMock"이 비
   동기 함수에 사용되고 "MagicMock"이 나머지에 사용됩니다.

   *spec*의 더 강력한 형태는 *autospec*입니다. "autospec=True"를 설정
   하면 치환될 객체의 사양으로 모의 객체가 만들어집니다. 모의 객체의
   모든 어트리뷰트는 또한 치환되는 객체의 해당 어트리뷰트의 사양을 갖
   습니다. 모킹되는 메서드와 함수는 인자를 검사하고 잘못된 서명으로 호
   출되면 "TypeError"를 발생시킵니다. 클래스를 치환하는 모의 객체의 경
   우, 반환 값('인스턴스')은 클래스와 같은 사양을 갖습니다.
   "create_autospec()" 함수와 자동 사양을 참조하십시오.

   "autospec=True" 대신 "autospec=some_object"를 전달하여 치환되는 것
   대신 임의의 객체를 사양으로 사용할 수 있습니다.

   기본적으로 "patch()"는 존재하지 않는 어트리뷰트를 치환하지 못합니다
   . "create=True"를 전달하고, 어트리뷰트가 존재하지 않으면, 패치된 함
   수가 호출될 때 patch가 어트리뷰트를 만들고 패치된 함수가 종료된 후
   다시 삭제합니다. 이는 프로덕션 코드가 실행 시간에 만드는 어트리뷰트
   에 대해 테스트를 작성하는 데 유용합니다. 위험할 수 있어서 기본적으
   로 꺼져있습니다. 이 기능을 켜면 실제로 존재하지 않는 API에 대해 통
   과하는 테스트를 작성할 수 있습니다!

   참고:

     버전 3.5에서 변경: 모듈에 있는 내장(builtins)을 패치하는 경우
     "create=True"를 전달할 필요가 없습니다, 기본적으로 추가됩니다.

   패치는 "TestCase" 클래스 데코레이터로 사용할 수 있습니다. 클래스의
   각 테스트 메서드를 데코레이트 하여 작동합니다. 테스트 메서드가 공통
   패치 집합을 공유할 때 관리용 코드가 줄어듭니다. "patch()"는
   "patch.TEST_PREFIX"로 시작하는 메서드 이름을 조회하는 것으로 테스트
   를 찾습니다. 기본적으로 이것은 "'test'"인데, "unittest"가 테스트를
   찾는 방식과 일치합니다. "patch.TEST_PREFIX"를 설정하여 대체 접두사
   를 지정할 수 있습니다.

   with 문에서 patch를 컨텍스트 관리자로 사용할 수 있습니다. 여기서 패
   치는 with 문 다음에 들여쓰기 된 블록에 적용됩니다. "as"를 사용하면
   패치된 객체는 "as" 뒤에 오는 이름으로 연결됩니다; "patch()"가 모의
   객체를 만들 때 매우 유용합니다.

   "patch()" takes arbitrary keyword arguments. These will be passed
   to the "Mock" (or *new_callable*) on construction.

   "patch.dict(...)", "patch.multiple(...)" 및 "patch.object(...)"는
   대체 사용 사례에 사용할 수 있습니다.

"patch()"를 함수 데코레이터로 사용하여, 모의 객체를 만들고 데코레이트
된 함수에 전달합니다:

   >>> @patch('__main__.SomeClass')
   ... def function(normal_argument, mock_class):
   ...     print(mock_class is SomeClass)
   ...
   >>> function(None)
   True

클래스를 패치하면 클래스를 "MagicMock" *인스턴스*로 치환합니다. 테스트
대상 코드에서 클래스가 인스턴스 화 되면 사용될 모의 객체의
"return_value"가 됩니다.

클래스가 여러 번 인스턴스 화 되면 "side_effect"를 사용하여 매번 새 모
의 객체를 반환할 수 있습니다. 또는 *return_value*를 원하는 것으로 설정
할 수 있습니다.

패치된 클래스에서 *인스턴스*의 메서드에 대한 반환 값을 구성하려면
"return_value"에서 이를 수행해야 합니다. 예를 들면:

   >>> class Class:
   ...     def method(self):
   ...         pass
   ...
   >>> with patch('__main__.Class') as MockClass:
   ...     instance = MockClass.return_value
   ...     instance.method.return_value = 'foo'
   ...     assert Class() is instance
   ...     assert Class().method() == 'foo'
   ...

*spec*이나 *spec_set*을 사용하고 "patch()"가 *클래스*를 대체하고 있다
면, 만들어진 모의 객체의 반환 값은 같은 사양을 갖습니다.

   >>> Original = Class
   >>> patcher = patch('__main__.Class', spec=True)
   >>> MockClass = patcher.start()
   >>> instance = MockClass()
   >>> assert isinstance(instance, Original)
   >>> patcher.stop()

*new_callable* 인자는 생성된 모의 객체의 기본 "MagicMock"에 대한 대체
클래스를 사용하려고 할 때 유용합니다. 예를 들어, "NonCallableMock"을
사용하려면:

   >>> thing = object()
   >>> with patch('__main__.thing', new_callable=NonCallableMock) as mock_thing:
   ...     assert thing is mock_thing
   ...     thing()
   ...
   Traceback (most recent call last):
     ...
   TypeError: 'NonCallableMock' object is not callable

또 다른 사용 사례는 객체를 "io.StringIO" 인스턴스로 교체하는 것입니다:

   >>> from io import StringIO
   >>> def foo():
   ...     print('Something')
   ...
   >>> @patch('sys.stdout', new_callable=StringIO)
   ... def test(mock_stdout):
   ...     foo()
   ...     assert mock_stdout.getvalue() == 'Something\n'
   ...
   >>> test()

"patch()"가 여러분 대신 모의 객체를 만들 때, 보통 가장 먼저 해야 할 일
은 모의 객체를 구성하는 것입니다. 이 구성 중 일부는 patch 호출에서 수
행 할 수 있습니다. 호출에 전달하는 임의의 키워드는 만들어진 모의 객체
의 어트리뷰트를 설정하는 데 사용됩니다:

   >>> patcher = patch('__main__.thing', first='one', second='two')
   >>> mock_thing = patcher.start()
   >>> mock_thing.first
   'one'
   >>> mock_thing.second
   'two'

만들어진 모의 객체 어트리뷰트뿐만 아니라 자식 모의 객체의
"return_value"와 "side_effect"와 같은 어트리뷰트도 구성 할 수 있습니다
. 키워드 인자로 직접 전달하는 것은 문법적으로 유효하지 않지만, 이것들
을 키로 갖는 딕셔너리는 여전히 "**"를 사용하여 "patch()" 호출로 확장될
수 있습니다:

   >>> config = {'method.return_value': 3, 'other.side_effect': KeyError}
   >>> patcher = patch('__main__.thing', **config)
   >>> mock_thing = patcher.start()
   >>> mock_thing.method()
   3
   >>> mock_thing.other()
   Traceback (most recent call last):
     ...
   KeyError

기본적으로, 존재하지 않는 모듈의 함수(또는 클래스의 메서드나 어트리뷰
트)를 패치하려고 시도하면 "AttributeError"로 실패합니다:

   >>> @patch('sys.non_existing_attribute', 42)
   ... def test():
   ...     assert sys.non_existing_attribute == 42
   ...
   >>> test()
   Traceback (most recent call last):
     ...
   AttributeError: <module 'sys' (built-in)> does not have the attribute 'non_existing'

그러나 "patch()" 호출에 "create=True"를 추가하면 이전 예제가 기대한 대
로 작동합니다:

   >>> @patch('sys.non_existing_attribute', 42, create=True)
   ... def test(mock_stdout):
   ...     assert sys.non_existing_attribute == 42
   ...
   >>> test()

버전 3.8에서 변경: "patch()"는 이제 target이 비동기 함수면 "AsyncMock"
을 반환합니다.


patch.object
------------

patch.object(target, attribute, new=DEFAULT, spec=None, create=False, spec_set=None, autospec=None, new_callable=None, **kwargs)

   모의 객체로 객체(*target*)의 이름 있는 멤버(*attribute*)를 패치합니
   다.

   "patch.object()"는 데코레이터, 클래스 데코레이터 또는 컨텍스트 관리
   자로 사용할 수 있습니다. 인자 *new*, *spec*, *create*, *spec_set*,
   *autospec* 및 *new_callable*은 "patch()"와 같은 의미입니다.
   "patch()"와 마찬가지로, "patch.object()"는 만드는 모의 객체를 구성
   하기 위해 임의의 키워드 인자를 취합니다.

   클래스 데코레이터로 사용될 때, "patch.object()"는 감쌀 메서드를 선
   택하는 데 "patch.TEST_PREFIX"를 사용합니다.

세 개의 인자나 두 개의 인자로 "patch.object()"를 호출 할 수 있습니다.
세 개의 인자 형식은 패치 할 객체, 어트리뷰트 이름 및 어트리뷰트를 대체
할 객체를 취합니다.

두 개의 인자 형식으로 호출하면 대체 객체를 생략하고, 모의 객체가 만들
어져 데코레이트 된 함수에 대한 추가 인자로 전달됩니다:

>>> @patch.object(SomeClass, 'class_method')
... def test(mock_method):
...     SomeClass.class_method(3)
...     mock_method.assert_called_with(3)
...
>>> test()

*spec*, *create* 및 "patch.object()"에 대한 다른 인자는 "patch()"와 같
은 의미입니다.


patch.dict
----------

patch.dict(in_dict, values=(), clear=False, **kwargs)

   딕셔너리나 딕셔너리류 객체를 패치하고, 테스트 후에 딕셔너리를 원래
   상태로 복원합니다.

   *in_dict*는 딕셔너리나 컨테이너와 같은 매핑일 수 있습니다. 매핑이면
   적어도 가져오기(get), 설정(set) 및 삭제(delete)와 키 이터레이션을
   지원해야 합니다.

   *in_dict*는 딕셔너리 이름을 지정하는 문자열일 수도 있으며, 이때는
   임포트 해서 가져옵니다.

   *values*는 딕셔너리에 설정할 값의 딕셔너리일 수 있습니다. *values*
   는 "(key, value)" 쌍의 이터러블일 수도 있습니다.

   *clear*가 참이면 새 값이 설정되기 전에 딕셔너리가 지워집니다.

   딕셔너리에 값을 설정하기 위해 임의의 키워드 인자로 "patch.dict()"를
   호출할 수도 있습니다.

   버전 3.8에서 변경: "patch.dict()"는 이제 컨텍스트 관리자로 사용될
   때 패치된 딕셔너리를 반환합니다.

"patch.dict()"는 컨텍스트 관리자, 데코레이터 또는 클래스 데코레이터로
사용할 수 있습니다:

>>> foo = {}
>>> @patch.dict(foo, {'newkey': 'newvalue'})
... def test():
...     assert foo == {'newkey': 'newvalue'}
>>> test()
>>> assert foo == {}

클래스 데코레이터로 사용될 때 "patch.dict()"는 감쌀 메서드를 선택하는
데 "patch.TEST_PREFIX"(기본값은 "'test'")를 따릅니다:

>>> import os
>>> import unittest
>>> from unittest.mock import patch
>>> @patch.dict('os.environ', {'newkey': 'newvalue'})
... class TestSample(unittest.TestCase):
...     def test_sample(self):
...         self.assertEqual(os.environ['newkey'], 'newvalue')

테스트에 다른 접두사를 사용하려면, "patch.TEST_PREFIX"를 설정하여 패처
에 다른 접두사를 알릴 수 있습니다. 값을 변경하는 방법에 대한 자세한 내
용은 TEST_PREFIX를 참조하십시오.

"patch.dict()"를 사용하여 멤버를 딕셔너리에 추가하고 (또는 단순히 테스
트에서 딕셔너리를 변경하고) 테스트가 끝나면 딕셔너리가 복원되도록 할
수 있습니다.

>>> foo = {}
>>> with patch.dict(foo, {'newkey': 'newvalue'}) as patched_foo:
...     assert foo == {'newkey': 'newvalue'}
...     assert patched_foo == {'newkey': 'newvalue'}
...     # You can add, update or delete keys of foo (or patched_foo, it's the same dict)
...     patched_foo['spam'] = 'eggs'
...
>>> assert foo == {}
>>> assert patched_foo == {}

>>> import os
>>> with patch.dict('os.environ', {'newkey': 'newvalue'}):
...     print(os.environ['newkey'])
...
newvalue
>>> assert 'newkey' not in os.environ

"patch.dict()" 호출에서 키워드를 사용하여 딕셔너리에 값을 설정할 수 있
습니다:

>>> mymodule = MagicMock()
>>> mymodule.function.return_value = 'fish'
>>> with patch.dict('sys.modules', mymodule=mymodule):
...     import mymodule
...     mymodule.function('some', 'args')
...
'fish'

"patch.dict()"는 실제로 딕셔너리가 아닌 딕셔너리류 객체와 함께 사용할
수 있습니다. 최소한 아이템 가져오기, 설정하기, 삭제하기 및 이터레이션
이나 멤버십 검사를 지원해야 합니다. 이것은 매직 메서드
"__getitem__()", "__setitem__()", "__delitem__()" 및 "__iter__()"나
"__contains__()"에 해당합니다.

>>> class Container:
...     def __init__(self):
...         self.values = {}
...     def __getitem__(self, name):
...         return self.values[name]
...     def __setitem__(self, name, value):
...         self.values[name] = value
...     def __delitem__(self, name):
...         del self.values[name]
...     def __iter__(self):
...         return iter(self.values)
...
>>> thing = Container()
>>> thing['one'] = 1
>>> with patch.dict(thing, one=2, two=3):
...     assert thing['one'] == 2
...     assert thing['two'] == 3
...
>>> assert thing['one'] == 1
>>> assert list(thing) == ['one']


patch.multiple
--------------

patch.multiple(target, spec=None, create=False, spec_set=None, autospec=None, new_callable=None, **kwargs)

   한 번의 호출로 여러 패치를 수행합니다. 패치할 객체(객체나 임포트로
   객체를 가져올 문자열로)와 패치에 대한 키워드 인자를 취합니다:

      with patch.multiple(settings, FIRST_PATCH='one', SECOND_PATCH='two'):
          ...

   "patch.multiple()"가 모의 객체를 만들기를 원하면 "DEFAULT"를 값으로
   사용하십시오. 이 경우 만들어진 모의 객체는 키워드로 데코레이트 된
   함수로 전달되며, "patch.multiple()"이 컨텍스트 관리자로 사용될 때는
   딕셔너리가 반환됩니다.

   "patch.multiple()"은 데코레이터, 클래스 데코레이터 또는 컨텍스트 관
   리자로 사용할 수 있습니다. *spec*, *spec_set*, *create*, *autospec*
   및 *new_callable* 인자는 "patch()"와 같은 의미입니다. 이 인자는
   "patch.multiple()"이 수행한 *모든* 패치에 적용됩니다.

   클래스 데코레이터로 사용될 때 "patch.multiple()"은 감쌀 메서드를 선
   택하는 데 "patch.TEST_PREFIX"를 사용합니다.

"patch.multiple()"가 모의 객체를 만들기를 원하면 "DEFAULT"를 값으로 사
용할 수 있습니다. "patch.multiple()"을 데코레이터로 사용하면 만들어진
모의 객체가 키워드로 데코레이트 된 함수에 전달됩니다.

   >>> thing = object()
   >>> other = object()

   >>> @patch.multiple('__main__', thing=DEFAULT, other=DEFAULT)
   ... def test_function(thing, other):
   ...     assert isinstance(thing, MagicMock)
   ...     assert isinstance(other, MagicMock)
   ...
   >>> test_function()

"patch.multiple()"은 다른 "patch" 데코레이터와 중첩될 수 있지만, 키워
드로 전달된 인자를 "patch()"가 만든 모든 표준 인자들 *뒤*에 넣습니다:

   >>> @patch('sys.exit')
   ... @patch.multiple('__main__', thing=DEFAULT, other=DEFAULT)
   ... def test_function(mock_exit, other, thing):
   ...     assert 'other' in repr(other)
   ...     assert 'thing' in repr(thing)
   ...     assert 'exit' in repr(mock_exit)
   ...
   >>> test_function()

"patch.multiple()"가 컨텍스트 관리자로 사용되면, 컨텍스트 관리자가 반
환한 값은 만들어진 모의 객체 이름을 키로 갖는 딕셔너리입니다:

   >>> with patch.multiple('__main__', thing=DEFAULT, other=DEFAULT) as values:
   ...     assert 'other' in repr(values['other'])
   ...     assert 'thing' in repr(values['thing'])
   ...     assert values['thing'] is thing
   ...     assert values['other'] is other
   ...


패처 메서드: start와 stop
-------------------------

모든 패처에는 "start()"와 "stop()" 메서드가 있습니다. 이를 통해
"setUp" 메서드나 데코레이터를 중첩하거나 with 문을 사용하지 않고 여러
패치를 수행하려는 곳에서 패치를 수행하는 것이 더 간단해집니다.

이것들을 사용하려면 "patch()", "patch.object()" 또는 "patch.dict()"를
정상적으로 호출하고 반환된 "patcher" 객체에 대한 참조를 유지하십시오.
그런 다음 "start()"를 호출하여 패치를 제자리에 놓고 "stop()"을 사용하
여 패치를 취소할 수 있습니다.

"patch()"를 사용하여 모의 객체를 만들면 "patcher.start" 호출로 반환됩
니다.

   >>> patcher = patch('package.module.ClassName')
   >>> from package import module
   >>> original = module.ClassName
   >>> new_mock = patcher.start()
   >>> assert module.ClassName is not original
   >>> assert module.ClassName is new_mock
   >>> patcher.stop()
   >>> assert module.ClassName is original
   >>> assert module.ClassName is not new_mock

일반적인 사용 사례는 "TestCase"의 "setUp" 메서드에서 여러 패치를 수행
하는 것입니다:

   >>> class MyTest(unittest.TestCase):
   ...     def setUp(self):
   ...         self.patcher1 = patch('package.module.Class1')
   ...         self.patcher2 = patch('package.module.Class2')
   ...         self.MockClass1 = self.patcher1.start()
   ...         self.MockClass2 = self.patcher2.start()
   ...
   ...     def tearDown(self):
   ...         self.patcher1.stop()
   ...         self.patcher2.stop()
   ...
   ...     def test_something(self):
   ...         assert package.module.Class1 is self.MockClass1
   ...         assert package.module.Class2 is self.MockClass2
   ...
   >>> MyTest('test_something').run()

조심:

  이 기법을 사용하는 경우 "stop"을 호출하여 패치가 "실행 취소" 되도록
  해야 합니다. "setUp"에서 예외가 발생하면 "tearDown"이 호출되지 않기
  때문에, 이것은 생각보다 까다로울 수 있습니다.
  "unittest.TestCase.addCleanup()"은 이것을 더 쉽게 만듭니다:

     >>> class MyTest(unittest.TestCase):
     ...     def setUp(self):
     ...         patcher = patch('package.module.Class')
     ...         self.MockClass = patcher.start()
     ...         self.addCleanup(patcher.stop)
     ...
     ...     def test_something(self):
     ...         assert package.module.Class is self.MockClass
     ...

  추가 보너스로 더는 "patcher" 객체에 대한 참조를 유지할 필요가 없습니
  다.

"patch.stopall()"을 사용하여 시작된 모든 패치를 중지할 수도 있습니다.

patch.stopall()

   모든 활성 패치를 중지합니다. "start"로 시작한 패치만 중지합니다.


내장 패치
---------

모듈 내의 어떤 내장(builtins)도 패치 할 수 있습니다. 다음 예제는 내장
"ord()"를 패치합니다:

   >>> @patch('__main__.ord')
   ... def test(mock_ord):
   ...     mock_ord.return_value = 101
   ...     print(ord('c'))
   ...
   >>> test()
   101


TEST_PREFIX
-----------

모든 패처를 클래스 데코레이터로 사용할 수 있습니다. 이런 식으로 사용하
면 클래스의 모든 테스트 메서드를 감쌉니다. 패처는 "'test'"로 시작하는
메서드를 테스트 메서드로 인식합니다. 이것은 "unittest.TestLoader"가 기
본적으로 테스트 메서드를 찾는 것과 같은 방법입니다.

테스트에 다른 접두사를 사용하고 싶을 수도 있습니다.
"patch.TEST_PREFIX"를 설정하여 다른 접두사를 패처에 알릴 수 있습니다:

   >>> patch.TEST_PREFIX = 'foo'
   >>> value = 3
   >>>
   >>> @patch('__main__.value', 'not three')
   ... class Thing:
   ...     def foo_one(self):
   ...         print(value)
   ...     def foo_two(self):
   ...         print(value)
   ...
   >>>
   >>> Thing().foo_one()
   not three
   >>> Thing().foo_two()
   not three
   >>> value
   3


패치 데코레이터 중첩하기
------------------------

여러 패치를 수행하려면 단순히 데코레이터를 쌓으면 됩니다.

이 패턴을 사용하여 여러 패치 데코레이터를 쌓을 수 있습니다:

>>> @patch.object(SomeClass, 'class_method')
... @patch.object(SomeClass, 'static_method')
... def test(mock1, mock2):
...     assert SomeClass.static_method is mock1
...     assert SomeClass.class_method is mock2
...     SomeClass.static_method('foo')
...     SomeClass.class_method('bar')
...     return mock1, mock2
...
>>> mock1, mock2 = test()
>>> mock1.assert_called_once_with('foo')
>>> mock2.assert_called_once_with('bar')

데코레이터는 아래에서 위쪽으로 적용됨에 유의하십시오. 이것은 파이썬이
데코레이터를 적용하는 표준 방식입니다. 생성된 모의 객체가 테스트 함수
에 전달되는 순서는 이 순서와 일치합니다.


패치할 곳
---------

"patch()"는 *name*이 가리키는 객체를 다른 객체로 (임시로) 변경하여 작
동합니다. 개별 객체를 가리키는 많은 이름이 있을 수 있어서, 패치가 작동
하려면 테스트 대상 시스템에서 사용하는 이름을 패치해야 합니다.

기본 원칙은 객체가 *조회되는* 곳을 패치하는 것입니다. 이것은 정의된 곳
과 반드시 같은 곳일 필요는 없습니다. 몇 가지 예가 이를 명확히 하는 데
도움이 됩니다.

테스트하려는 프로젝트가 다음 구조로 되어 있다고 가정하십시오:

   a.py
       -> Defines SomeClass

   b.py
       -> from a import SomeClass
       -> some_function instantiates SomeClass

이제 "some_function"을 테스트하고 싶지만, "patch()"를 사용하여
"SomeClass"를 모킹하고 싶습니다. 문제는 모듈 b를 임포트 할 때 모듈 a에
서 "SomeClass"를 임포트해야 한다는 것입니다. "patch()"를 사용하여
"a.SomeClass"를 모킹하면 테스트에 영향을 미치지 않습니다; 모듈 b는 이
미 *실제* "SomeClass"에 대한 참조를 가지고 있으며 패치가 효과가 없는
것처럼 보입니다.

핵심은 "SomeClass"가 사용되는 곳(또는 그것을 조회하는 곳)을 패치하는
것입니다. 이 경우 "some_function"은 우리가 임포트 한 모듈 b에서
"SomeClass"를 조회합니다. 패치는 다음과 같아야 합니다:

   @patch('b.SomeClass')

하지만, "from a import SomeClass" 대신 모듈 b가 "import a"를 수행하고
"some_function"이 "a.SomeClass"를 사용하는 대체 시나리오를 생각해보십
시오. 이 두 가지 임포트 형식은 모두 일반적입니다. 이 경우 패치하려는
클래스가 모듈에서 조회되므로 대신 "a.SomeClass"를 패치해야 합니다:

   @patch('a.SomeClass')


디스크립터와 프락시 객체 패치하기
---------------------------------

patch 와 patch.object 모두 디스크립터를 올바르게 패치하고 복원합니다:
클래스 메서드, 정적 메서드 및 프로퍼티. 이것들을 인스턴스가 아닌 *클래
스*에서 패치해야 합니다. 이들은 또한 장고 settings 객체와 같이 어트리
뷰트 액세스를 프락시 하는 *일부* 객체에서도 작동합니다.


MagicMock과 매직 메서드 지원
============================


매직 메서드 모킹하기
--------------------

"Mock"은 "매직 메서드"라고도 하는 파이썬 프로토콜 메서드 모킹을 지원합
니다. 이를 통해 모의 객체가 컨테이너나 파이썬 프로토콜을 구현하는 다른
객체를 대체할 수 있습니다.

매직 메서드는 일반 메서드와는 다르게 조회되므로 [2], 이 지원은 특별히
구현되었습니다. 즉, 특정 매직 메서드만 지원됩니다. 지원되는 목록에 이
들이 *거의* 모두 포함됩니다. 누락된 것이 있으면 알려주십시오.

관심 있는 메서드를 함수나 모의 객체 인스턴스로 설정하여 매직 메서드를
모킹합니다. 함수를 사용하면 *반드시* "self"를 첫 번째 인자로 취해야 합
니다 [3].

>>> def __str__(self):
...     return 'fooble'
...
>>> mock = Mock()
>>> mock.__str__ = __str__
>>> str(mock)
'fooble'

>>> mock = Mock()
>>> mock.__str__ = Mock()
>>> mock.__str__.return_value = 'fooble'
>>> str(mock)
'fooble'

>>> mock = Mock()
>>> mock.__iter__ = Mock(return_value=iter([]))
>>> list(mock)
[]

이것의 한 가지 사용 사례는 "with" 문에서 컨텍스트 관리자로 사용되는 객
체를 모킹하는 것입니다:

>>> mock = Mock()
>>> mock.__enter__ = Mock(return_value='foo')
>>> mock.__exit__ = Mock(return_value=False)
>>> with mock as m:
...     assert m == 'foo'
...
>>> mock.__enter__.assert_called_with()
>>> mock.__exit__.assert_called_with(None, None, None)

매직 메서드 호출은 "method_calls"에는 나타나지 않지만, "mock_calls"에
기록됩니다.

참고:

  *spec* 키워드 인자를 사용하여 모의 객체를 만들면 spec에 없는 매직 메
  서드를 설정하려고 시도할 때 "AttributeError"가 발생합니다.

지원되는 매직 메서드의 전체 목록은 다음과 같습니다:

* "__hash__", "__sizeof__", "__repr__" 및 "__str__"

* "__dir__", "__format__" 및 "__subclasses__"

* "__round__", "__floor__", "__trunc__" 및 "__ceil__"

* 비교: "__lt__", "__gt__", "__le__", "__ge__", "__eq__" 및 "__ne__"

* 컨테이너 메서드: "__getitem__", "__setitem__", "__delitem__",
  "__contains__", "__len__", "__iter__", "__reversed__" 및
  "__missing__"

* 컨텍스트 관리자: "__enter__", "__exit__", "__aenter__" 및
  "__aexit__"

* 단항 숫자 메서드: "__neg__", "__pos__" 및 "__invert__"

* 숫자 메서드 (뒤집히거나 제자리 변형 포함) : "__add__", "__sub__",
  "__mul__", "__matmul__", "__div__", "__truediv__", "__floordiv__",
  "__mod__", "__divmod__", "__lshift__", "__rshift__", "__and__",
  "__xor__", "__or__" 및 "__pow__"

* 숫자 변환 메서드: "__complex__", "__int__", "__float__" 및
  "__index__"

* 디스크립터 메서드: "__get__", "__set__" 및 "__delete__"

* 피클링: "__reduce__", "__reduce_ex__", "__getinitargs__",
  "__getnewargs__", "__getstate__" 및 "__setstate__"

* 파일 시스템 경로 표현: "__fspath__"

* 비동기 이터레이션 메서드: "__aiter__"와 "__anext__"

버전 3.8에서 변경: "os.PathLike.__fspath__()"에 대한 지원이 추가되었습
니다.

버전 3.8에서 변경: "__aenter__", "__aexit__", "__aiter__" 및
"__anext__"에 대한 지원이 추가되었습니다.

다음과 같은 메서드가 존재하지만, 모의 객체가 사용 중이거나, 동적으로
설정할 수 없거나, 문제를 일으킬 수 있어서 지원되지 *않습니다*:

* "__getattr__", "__setattr__", "__init__" 및 "__new__"

* "__prepare__", "__instancecheck__", "__subclasscheck__", "__del__"


매직 모의 객체
--------------

두 가지 "MagicMock" 변형이 있습니다: "MagicMock"과
"NonCallableMagicMock".

class unittest.mock.MagicMock(*args, **kw)

   "MagicMock"은 대부분의 매직 메서드의 기본 구현이 있는 "Mock"의 서브
   클래스입니다. 매직 메서드를 직접 구성하지 않고도 "MagicMock"을 사용
   할 수 있습니다.

   생성자 매개 변수는 "Mock"과 같은 의미입니다.

   *spec*이나 *spec_set* 인자를 사용하면 *오직* 사양에 존재하는 매직
   메서드만 만들어집니다.

class unittest.mock.NonCallableMagicMock(*args, **kw)

   콜러블이 아닌 "MagicMock" 버전.

   생성자 매개 변수는 콜러블이 아닌 모의 객체에 의미가 없는
   *return_value*와 *side_effect*를 제외하고 "MagicMock"과 같은 의미입
   니다.

매직 메서드는 "MagicMock" 객체로 설정되므로, 일반적인 방법으로 구성하
고 사용할 수 있습니다:

>>> mock = MagicMock()
>>> mock[3] = 'fish'
>>> mock.__setitem__.assert_called_with(3, 'fish')
>>> mock.__getitem__.return_value = 'result'
>>> mock[2]
'result'

기본적으로 많은 프로토콜 메서드는 특정 형의 객체를 반환하도록 요구합니
다. 이러한 메서드는 기본 반환 값으로 사전 구성되어 있어서, 반환 값에
관심이 없을 때 아무 조처를 하지 않아도 사용할 수 있습니다. 기본값을 변
경하고 싶으면, 여전히 반환 값을 수동으로 *설정*할 수 있습니다.

메서드와 기본값:

* "__lt__": "NotImplemented"

* "__gt__": "NotImplemented"

* "__le__": "NotImplemented"

* "__ge__": "NotImplemented"

* "__int__": "1"

* "__contains__": "False"

* "__len__": "0"

* "__iter__": "iter([])"

* "__exit__": "False"

* "__aexit__": "False"

* "__complex__": "1j"

* "__float__": "1.0"

* "__bool__": "True"

* "__index__": "1"

* "__hash__": 모의 객체의 기본 hash

* "__str__": 모의 객체의 기본 str

* "__sizeof__": 모의 객체의 기본 sizeof

예를 들면:

>>> mock = MagicMock()
>>> int(mock)
1
>>> len(mock)
0
>>> list(mock)
[]
>>> object() in mock
False

두 동등 비교 메서드 "__eq__()"와 "__ne__()"는 특별합니다. 이들의 반환
값을 변경하여 다른 것을 반환하지 않는 한, "side_effect" 어트리뷰트를
사용하여 아이덴티티에 대한 기본 동등 비교를 수행합니다:

   >>> MagicMock() == 3
   False
   >>> MagicMock() != 3
   True
   >>> mock = MagicMock()
   >>> mock.__eq__.return_value = True
   >>> mock == 3
   True

"MagicMock.__iter__()"의 반환 값은 임의의 이터러블 객체일 수 있으며 이
터레이터일 필요는 없습니다:

>>> mock = MagicMock()
>>> mock.__iter__.return_value = ['a', 'b', 'c']
>>> list(mock)
['a', 'b', 'c']
>>> list(mock)
['a', 'b', 'c']

반환 값이 이터레이터면, 일단 이터레이트 하면 이를 소진하고 후속 이터레
이션은 빈 목록을 줍니다:

>>> mock.__iter__.return_value = iter(['a', 'b', 'c'])
>>> list(mock)
['a', 'b', 'c']
>>> list(mock)
[]

"MagicMock"에는 불분명하고 쓸모없는 일부를 제외하고 지원되는 모든 매직
메서드가 구성되어 있습니다. 원한다면 여전히 설정할 수 있습니다.

"MagicMock"에서 지원되지만, 기본적으로 설정되지 않는 매직 메서드는 다
음과 같습니다:

* "__subclasses__"

* "__dir__"

* "__format__"

* "__get__", "__set__" 및 "__delete__"

* "__reversed__"와 "__missing__"

* "__reduce__", "__reduce_ex__", "__getinitargs__", "__getnewargs__",
  "__getstate__" 및 "__setstate__"

* "__getformat__"과 "__setformat__"

[2] 매직 메서드는 인스턴스가 아닌 클래스에서 조회되어야 합니다. 다른
    버전의 파이썬은 이 규칙을 적용하는 데 일관적이지 않습니다. 지원되
    는 프로토콜 메서드는 지원되는 모든 버전의 파이썬에서 작동해야 합니
    다.

[3] 이 함수는 기본적으로 클래스에 연결되어 있지만, 각 "Mock" 인스턴스
    는 다른 것들과 격리되어 있습니다.


도우미
======


sentinel
--------

unittest.mock.sentinel

   "sentinel" 객체는 테스트에 고유한(unique) 객체를 제공하는 편리한 방
   법을 제공합니다.

   어트리뷰트는 이름으로 어트리뷰트에 액세스할 때 요청에 따라 만들어집
   니다. 같은 어트리뷰트에 액세스하면 항상 같은 객체가 반환됩니다. 반
   환된 객체는 테스트 실패 메시지를 읽을 수 있도록 적절한 repr을 갖습
   니다.

   버전 3.7에서 변경: "sentinel" 어트리뷰트는 이제 "복사"되거나 "피클"
   될 때 아이덴티티를 유지합니다.

때로 테스트할 때 특정 객체가 다른 메서드에 대한 인자로 전달되거나 반환
되는지 테스트해야 할 때가 있습니다. 이것을 테스트하기 위해 이름 붙은
sentinel 객체를 만드는 것이 일반적일 수 있습니다. "sentinel"은 이와 같
은 객체의 아이덴티티를 만들고 테스트하는 편리한 방법을 제공합니다.

이 예에서는 "method"를 "sentinel.some_object"를 반환하도록 몽키 패치합
니다:

>>> real = ProductionClass()
>>> real.method = Mock(name="method")
>>> real.method.return_value = sentinel.some_object
>>> result = real.method()
>>> assert result is sentinel.some_object
>>> sentinel.some_object
sentinel.some_object


DEFAULT
-------

unittest.mock.DEFAULT

   "DEFAULT" 객체는 미리 만들어진 sentinel(실제로 "sentinel.DEFAULT")
   입니다. "side_effect" 함수에서 일반 반환 값을 사용해야 함을 나타내
   는 데 사용할 수 있습니다.


call
----

unittest.mock.call(*args, **kwargs)

   "call()"은 "call_args", "call_args_list", "mock_calls" 및
   "method_calls"와 비교할 때, 더 간단한 어서션을 만들기 위한 도우미
   객체입니다. "call()"은 "assert_has_calls()"와 함께 사용할 수도 있습
   니다.

   >>> m = MagicMock(return_value=None)
   >>> m(1, 2, a='foo', b='bar')
   >>> m()
   >>> m.call_args_list == [call(1, 2, a='foo', b='bar'), call()]
   True

call.call_list()

   여러 호출을 나타내는 호출 객체의 경우, "call_list()"는 마지막 호출
   뿐만 아니라 모든 중간 호출의 목록을 반환합니다.

"call_list"는 "연쇄 호출(chained calls)"에 대한 어서션을 만드는 데 특
히 유용합니다. 연쇄 호출은 한 줄의 코드에 있는 여러 번의 호출입니다.
이로 인해 모의 객체의 "mock_calls"에 여러 항목이 생성됩니다. 호출 시퀀
스를 수동으로 구성하는 것은 지루할 수 있습니다.

"call_list()"는 같은 연쇄 호출에서 호출 시퀀스를 구성 할 수 있습니다.:

>>> m = MagicMock()
>>> m(1).method(arg='foo').other('bar')(2.0)
<MagicMock name='mock().method().other()()' id='...'>
>>> kall = call(1).method(arg='foo').other('bar')(2.0)
>>> kall.call_list()
[call(1),
 call().method(arg='foo'),
 call().method().other('bar'),
 call().method().other()(2.0)]
>>> m.mock_calls == kall.call_list()
True

"call" 객체는 구성 방식에 따라 (위치 인자, 키워드 인자)나 (이름, 위치
인자, 키워드 인자)의 튜플입니다. 이것들을 직접 만들 때 특별히 흥미롭지
는 않지만, "Mock.call_args", "Mock.call_args_list" 및
"Mock.mock_calls" 어트리뷰트에 있는 "call" 객체는 포함된 개별 인자를
얻기 위해 검사될 수 있습니다.

"Mock.call_args"와 "Mock.call_args_list"에 있는 "call" 객체는 (위치 인
자, 키워드 인자)의 2-튜플이지만, "Mock.mock_calls"에 있는 "call" 객체
는, 여러분이 직접 생성하는 객체와 함께, (이름, 위치 인자, 키워드 인자)
의 3-튜플입니다.

이들의 "튜플성(tupleness)"을 사용하여 더 복잡한 검사와 어서션을 위해
개별 인자를 가져올 수 있습니다. 위치 인자는 튜플(위치 인자가 없으면 비
어있는 튜플)이고 키워드 인자는 딕셔너리입니다:

>>> m = MagicMock(return_value=None)
>>> m(1, 2, 3, arg='one', arg2='two')
>>> kall = m.call_args
>>> kall.args
(1, 2, 3)
>>> kall.kwargs
{'arg': 'one', 'arg2': 'two'}
>>> kall.args is kall[0]
True
>>> kall.kwargs is kall[1]
True

>>> m = MagicMock()
>>> m.foo(4, 5, 6, arg='two', arg2='three')
<MagicMock name='mock.foo()' id='...'>
>>> kall = m.mock_calls[0]
>>> name, args, kwargs = kall
>>> name
'foo'
>>> args
(4, 5, 6)
>>> kwargs
{'arg': 'two', 'arg2': 'three'}
>>> name is m.mock_calls[0][0]
True


create_autospec
---------------

unittest.mock.create_autospec(spec, spec_set=False, instance=False, **kwargs)

   다른 객체를 사양으로 사용하여 모의 객체를 만듭니다. 모의 객체 어트
   리뷰트는 *spec* 객체의 해당 어트리뷰트를 사양으로 사용합니다.

   모킹되는 함수나 메서드는 올바른 서명으로 호출되도록 인자를 점검합니
   다.

   *spec_set*이 "True"이면 사양 객체에 존재하지 않는 어트리뷰트를 설정
   하려는 시도는 "AttributeError"를 발생시킵니다.

   클래스가 사양으로 사용되면 모의 객체의 반환 값(클래스의 인스턴스)은
   같은 사양을 갖습니다. "instance=True"를 전달하여 클래스를 인스턴스
   객체의 사양으로 사용할 수 있습니다. 반환된 모의 객체는 모의 객체의
   인스턴스가 콜러블일 때만 콜러블입니다.

   "create_autospec()"은 또한 만들어진 모의 객체의 생성자에 전달되는
   임의의 키워드 인자를 취합니다.

"create_autospec()"과 "patch()"에 대한 *autospec* 인자로 자동 사양을
사용하는 방법에 대한 예는 자동 사양을 참조하십시오.

버전 3.8에서 변경: 대상이 비동기 함수이면 "create_autospec()"은 이제
"AsyncMock"을 반환합니다.


ANY
---

unittest.mock.ANY

때로는 모의 객체 호출에서 인자의 *일부*에 대한 어서션을 만들 필요가 있
지만, 일부 인자에는 신경 쓰지 않거나 "call_args"에서 개별적으로 꺼내어
더 복잡한 어서션을 만들고 싶을 수도 있습니다.

특정 인자를 무시하려면 *모든 것*과 같다고 비교되는 객체를 전달할 수 있
습니다. "assert_called_with()"와 "assert_called_once_with()"에 대한 호
출은 전달된 내용과 관계없이 성공합니다.

>>> mock = Mock(return_value=None)
>>> mock('foo', bar=object())
>>> mock.assert_called_once_with('foo', bar=ANY)

"ANY"는 "mock_calls"와 같은 호출 리스트와 비교할 때도 사용할 수 있습니
다.:

>>> m = MagicMock(return_value=None)
>>> m(1)
>>> m(1, 2)
>>> m(object())
>>> m.mock_calls == [call(1), call(1, 2), ANY]
True


FILTER_DIR
----------

unittest.mock.FILTER_DIR

"FILTER_DIR"은 모의 객체가 "dir()"에 응답하는 방식을 제어하는 모듈 수
준 변수입니다 (파이썬 2.6 이상에서만). 기본값은 "True"이며, 아래 설명
된 필터링을 사용하여 유용한 멤버만 표시합니다. 이 필터링이 마음에 들지
않거나 진단 목적으로 필터를 꺼야 하면, "mock.FILTER_DIR = False"를 설
정하십시오.

필터링을 켜면, "dir(some_mock)"는 유용한 어트리뷰트만 표시하고 일반적
으로 표시되지 않는 동적으로 만들어진 어트리뷰트를 포함합니다. *spec*(
또는 물론 *autospec*)으로 모의 객체를 만들었으면, 아직 액세스하지 않았
다 할지라도 원본의 모든 어트리뷰트가 표시됩니다:

   >>> dir(Mock())
   ['assert_any_call',
    'assert_called',
    'assert_called_once',
    'assert_called_once_with',
    'assert_called_with',
    'assert_has_calls',
    'assert_not_called',
    'attach_mock',
    ...
   >>> from urllib import request
   >>> dir(Mock(spec=request))
   ['AbstractBasicAuthHandler',
    'AbstractDigestAuthHandler',
    'AbstractHTTPHandler',
    'BaseHandler',
    ...

"Mock"에 대해 "dir()"을 호출한 결과에서 그다지 유용하지 않은 (모킹되는
대상이 아닌 "Mock" 전용) 밑줄과 이중 밑줄 접두어 어트리뷰트가 필터링
되었습니다. 이 동작이 마음에 들지 않으면 모듈 수준 스위치 "FILTER_DIR"
를 설정하여 끌 수 있습니다.:

   >>> from unittest import mock
   >>> mock.FILTER_DIR = False
   >>> dir(mock.Mock())
   ['_NonCallableMock__get_return_value',
    '_NonCallableMock__get_side_effect',
    '_NonCallableMock__return_value_doc',
    '_NonCallableMock__set_return_value',
    '_NonCallableMock__set_side_effect',
    '__call__',
    '__class__',
    ...

또는 "vars(my_mock)"(인스턴스 멤버)과 "dir(type(my_mock))"(형 멤버)을
사용하여 "mock.FILTER_DIR"에 관계없이 필터링을 무시할 수 있습니다.


mock_open
---------

unittest.mock.mock_open(mock=None, read_data=None)

   "open()"의 사용을 대체하기 위한 모의 객체를 만드는 도우미 함수. 직
   접 호출되거나 컨텍스트 관리자로 사용되는 "open()"에 대해 작동합니다
   .

   *mock* 인자는 구성할 모의 객체입니다. "None"(기본값)이면 표준 파일
   핸들에서 사용 가능한 메서드나 어트리뷰트로 API가 제한된 "MagicMock"
   이 만들어집니다.

   *read_data*는 파일 핸들의 "read()", "readline()" 및 "readlines()"
   메서드가 반환할 문자열입니다. 이러한 메서드를 호출하면 *read_data*
   에서 데이터가 고갈될 때까지 데이터를 가져옵니다. 이러한 메서드의 모
   의 객체는 매우 단순합니다: *mock*이 호출될 때마다 *read_data*는 처
   음으로 되감깁니다. 테스트 되는 코드에 공급하는 데이터를 더 세밀하게
   제어하려면 이 모의 객체를 스스로 사용자 정의해야 합니다. 이것으로
   불충분하면, PyPI의 메모리 내 파일 시스템 패키지 중 하나가 테스트를
   위한 진짜 같은 파일 시스템을 제공할 수 있습니다.

   버전 3.4에서 변경: "readline()"과 "readlines()" 지원이 추가되었습니
   다. "read()"의 모의 객체는 호출마다 *read_data*를 반환하는 대신 소
   비하도록 변경되었습니다.

   버전 3.5에서 변경: *read_data*는 이제 *mock*을 호출할 때마다 재설정
   됩니다.

   버전 3.8에서 변경: 이터레이션(가령 for 루프)에서 *read_data*를 올바
   르게 소비하도록 구현에 "__iter__()"를 추가했습니다.

"open()"을 컨텍스트 관리자로 사용하는 것은 파일 핸들이 올바르게 닫히도
록 보장하는 좋은 방법이고 점차 일반화되고 있습니다:

   with open('/some/path', 'w') as f:
       f.write('something')

문제는 "open()"에 대한 호출을 모킹하더라도 컨텍스트 관리자로 사용되는
것은 *반환된 객체*라는 것입니다 (그리고 "__enter__()"와 "__exit__()"가
호출됩니다).

"MagicMock"으로 컨텍스트 관리자를 모킹하는 것은 도우미 함수가 유용할
만큼 충분히 일반적입니다.

   >>> m = mock_open()
   >>> with patch('__main__.open', m):
   ...     with open('foo', 'w') as h:
   ...         h.write('some stuff')
   ...
   >>> m.mock_calls
   [call('foo', 'w'),
    call().__enter__(),
    call().write('some stuff'),
    call().__exit__(None, None, None)]
   >>> m.assert_called_once_with('foo', 'w')
   >>> handle = m()
   >>> handle.write.assert_called_once_with('some stuff')

그리고 파일을 읽기 위해서는:

   >>> with patch('__main__.open', mock_open(read_data='bibble')) as m:
   ...     with open('foo') as h:
   ...         result = h.read()
   ...
   >>> m.assert_called_once_with('foo')
   >>> assert result == 'bibble'


자동 사양
---------

자동 사양은 기존의 "spec" 기능을 기반으로 합니다. 모의 객체 api를 원본
객체(사양)의 api로 제한하지만, 재귀적(게으르게(lazily) 구현되었습니다)
이라서 모의 객체의 어트리뷰트는 사양의 어트리뷰트와 같은 api만 갖습니
다. 또한 모킹된 함수 / 메서드는 원본과 같은 호출 서명을 가지므로 잘못
호출되면 "TypeError"를 발생시킵니다.

자동 사양이 작동하는 방식을 설명하기 전에, 이것이 필요한 이유는 이렇습
니다.

"Mock"은 매우 강력하고 유연한 객체이지만, 테스트 대상 시스템에서 객체
를 모킹할 때 두 가지 결함이 있습니다. 이러한 결함 중 하나는 "Mock" api
에만 해당하며 다른 하나는 모의 객체 사용에 대한 보다 일반적인 문제입니
다.

먼저 "Mock"과 관련된 문제입니다. "Mock"에는 "assert_called_with()"와
"assert_called_once_with()"라는 매우 편리한 두 가지 어서션 메서드가 있
습니다.

>>> mock = Mock(name='Thing', return_value=None)
>>> mock(1, 2, 3)
>>> mock.assert_called_once_with(1, 2, 3)
>>> mock(1, 2, 3)
>>> mock.assert_called_once_with(1, 2, 3)
Traceback (most recent call last):
 ...
AssertionError: Expected 'mock' to be called once. Called 2 times.

모의 객체는 요청 시 어트리뷰트를 자동 생성하고, 임의의 인자로 어트리뷰
트를 호출하도록 허락합니다, 이러한 어서트 메서드 중 하나의 철자를 틀리
면 어서션이 사라집니다:

   >>> mock = Mock(name='Thing', return_value=None)
   >>> mock(1, 2, 3)
   >>> mock.assret_called_once_with(4, 5, 6)

오타로 인해 테스트가 조용히 잘못 통과할 수 있습니다.

두 번째 문제는 모킹에 더 일반적입니다. 멤버 이름 등을 변경하는 등 일부
코드를 리팩토링하면, 여전히 *예전 api*를 사용하는 코드에 대한 테스트는
실제 객체 대신 모의 객체를 사용하면 모두 통과합니다. 이것은 코드가 손
상되어도 테스트를 모두 통과 할 수 있다는 뜻입니다.

이것이 단위 테스트뿐만 아니라 통합 테스트가 필요한 또 다른 이유입니다.
모든 것을 분리해서 테스트하는 것은 괜찮고 멋지지만, 단위들이 어떻게 "
서로 연결되어" 있는지 테스트하지 않으면 테스트가 발견할 수도 있을 버그
에 대한 여지가 여전히 많습니다.

"mock"은 이미 이에 도움이 되는 기능인 사양(speccing)을 제공합니다. 모
의 객체에 클래스나 인스턴스를 "spec"으로 사용하면, 실제 클래스에 존재
하는 모의 객체 어트리뷰트에만 액세스 할 수 있습니다:

>>> from urllib import request
>>> mock = Mock(spec=request.Request)
>>> mock.assret_called_with
Traceback (most recent call last):
 ...
AttributeError: Mock object has no attribute 'assret_called_with'

사양은 모의 객체 자체에만 적용되므로, 모의 객체의 메서드와 관계된 문제
는 여전히 있습니다:

   >>> mock.has_data()
   <mock.Mock object at 0x...>
   >>> mock.has_data.assret_called_with()

자동 사양은 이 문제를 해결합니다. "autospec=True"를 "patch()" /
"patch.object()"로 전달하거나 "create_autospec()" 함수를 사용하여 사양
이 있는 모의 객체를 만들 수 있습니다. "autospec=True" 인자를 "patch()"
에 사용하면 대체 중인 객체가 사양 객체로 사용됩니다. 사양화(speccing)
는 "게으르게(lazily)" 수행되므로 (모의 객체의 어트리뷰트에 액세스할 때
사양이 만들어집니다) 성능이 크게 저하되지 않고도 매우 복잡하거나 깊이
중첩된 객체(가령 모듈을 임포트 하는 모듈을 임포트 하는 모듈)와 함께 사
용할 수 있습니다.

사용 예는 다음과 같습니다:

   >>> from urllib import request
   >>> patcher = patch('__main__.request', autospec=True)
   >>> mock_request = patcher.start()
   >>> request is mock_request
   True
   >>> mock_request.Request
   <MagicMock name='request.Request' spec='Request' id='...'>

"request.Request"에 spec이 있음을 알 수 있습니다. "request.Request"는
생성자에서 두 개의 인자를 취합니다 (하나는 *self*입니다). 잘못 호출하
면 이렇게 됩니다:

   >>> req = request.Request()
   Traceback (most recent call last):
    ...
   TypeError: <lambda>() takes at least 2 arguments (1 given)

사양은 인스턴스 화 된 클래스(즉, 사양화된 모의 객체의 반환 값)에도 적
용됩니다:

   >>> req = request.Request('foo')
   >>> req
   <NonCallableMagicMock name='request.Request()' spec='Request' id='...'>

"Request" 객체는 콜러블이 아니므로, 모킹된 "request.Request"의 인스턴
스 화의 반환 값은 콜러블이 아닌 모의 객체입니다. 사양이 적용되면 어서
션에 오타가 있을 때 올바른 에러를 발생시킵니다:

   >>> req.add_header('spam', 'eggs')
   <MagicMock name='request.Request().add_header()' id='...'>
   >>> req.add_header.assret_called_with
   Traceback (most recent call last):
    ...
   AttributeError: Mock object has no attribute 'assret_called_with'
   >>> req.add_header.assert_called_with('spam', 'eggs')

많은 경우 단지 기존 "patch()" 호출에 "autospec=True"를 추가하면 오타와
api 변경으로 인한 버그로부터 보호할 수 있습니다.

"patch()"를 통해 *autospec*을 사용하는 것뿐만 아니라 자동 사양 모의 객
체를 직접 만들기 위한 "create_autospec()"도 있습니다:

>>> from urllib import request
>>> mock_request = create_autospec(request)
>>> mock_request.Request('foo', 'bar')
<NonCallableMagicMock name='mock.Request()' spec='Request' id='...'>

그러나 경고와 제한이 없는 것은 아니기 때문에 기본 동작이 아닙니다. 사
양 객체에서 사용 가능한 어트리뷰트를 알기 위해 autospec은 사양을 검사(
어트리뷰트를 액세스합니다)해야 합니다. 모의 객체 어트리뷰트를 탐색할
때 원본 객체의 대응하는 탐색이 수면 아래에서 발생합니다. 사양 객체 중
어느 하나가 코드 실행을 트리거 할 수 있는 프로퍼티나 디스크립터를 갖는
경우 자동 사양을 사용하지 못할 수 있습니다. 반면에, 내부 검사가 안전하
도록 객체를 설계하는 것이 훨씬 좋습니다 [4].

더 심각한 문제는 인스턴스 어트리뷰트가 "__init__()" 메서드에서 만들어
지고 클래스에 전혀 존재하지 않는 것이 일반적이라는 것입니다.
*autospec*은 동적으로 만들어진 어트리뷰트를 알 수 없으며 api를 가시적
어트리뷰트로 제한합니다.

   >>> class Something:
   ...   def __init__(self):
   ...     self.a = 33
   ...
   >>> with patch('__main__.Something', autospec=True):
   ...   thing = Something()
   ...   thing.a
   ...
   Traceback (most recent call last):
     ...
   AttributeError: Mock object has no attribute 'a'

이 문제를 해결하는 방법에는 몇 가지가 있습니다. 가장 쉬운, 하지만 가장
덜 성가시다고 할 수는 없는, 방법은 단순히 생성 후에 모의 객체에 필요한
어트리뷰트를 설정하는 것입니다. *autospec*은 사양에 존재하지 않는 어트
리뷰트를 꺼내는 것을 허락하지 않기 때문에 그것을 설정하는 것을 막지는
않습니다:

   >>> with patch('__main__.Something', autospec=True):
   ...   thing = Something()
   ...   thing.a = 33
   ...

존재하지 않는 어트리뷰트를 설정하지 *못하게 하는* *spec*과 *autospec*
의 더 적극적인 버전이 있습니다. 이것은 코드가 *오직* 유효한 어트리뷰트
만 설정하도록 보장하려는 경우 유용하지만, 명백히 이 특정 시나리오를 막
습니다:

>>> with patch('__main__.Something', autospec=True, spec_set=True):
...   thing = Something()
...   thing.a = 33
...
Traceback (most recent call last):
 ...
AttributeError: Mock object has no attribute 'a'

아마도 문제를 해결하는 가장 좋은 방법은 "__init__()"에서 초기화되는 인
스턴스 멤버의 기본값으로 클래스 어트리뷰트를 추가하는 것입니다.
"__init__()"에서 기본 어트리뷰트만 설정하고 있다면 클래스 어트리뷰트(
물론 인스턴스 간에 공유됩니다)를 통해 제공하는 것이 더 빠르기도 합니다
. 예를 들어

   class Something:
       a = 33

이것은 또 다른 문제를 일으킵니다. 나중에 다른 형의 객체가 될 멤버에 대
해 기본값 "None"을 제공하는 것이 일반적입니다. *아무런* 어트리뷰트나
메서드에도 액세스할 수 없도록 하므로 "None"은 사양으로 쓸모가 없습니다
. "None"은 *결코* 스펙으로 유용하지 않고, 일반적으로 다른 형의 멤버를
나타낼 것이기 때문에, autospec은 "None"으로 설정된 멤버의 사양을 사용
하지 않습니다. 이것들은 평범한 모의 객체일 것입니다 (아마도 -
MagicMock):

>>> class Something:
...     member = None
...
>>> mock = create_autospec(Something)
>>> mock.member.foo.bar.baz()
<MagicMock name='mock.member.foo.bar.baz()' id='...'>

프로덕션 클래스를 수정하여 기본값을 추가하는 것이 마음에 들지 않으면
더 많은 선택지가 있습니다. 이 중 하나는 단순히 클래스가 아닌 인스턴스
를 사양으로 사용하는 것입니다. 다른 하나는 프로덕션 클래스의 서브 클래
스를 만들고 프로덕션 클래스에 영향을 주지 않으면서 기본값을 서브 클래
스에 추가하는 것입니다. 이 두 가지 모두 사양으로 대체 객체를 사용해야
합니다. 고맙게도 "patch()"는 이것을 지원합니다 - 단순히 대체 객체를
*autospec* 인자로 전달할 수 있습니다:

   >>> class Something:
   ...   def __init__(self):
   ...     self.a = 33
   ...
   >>> class SomethingForTest(Something):
   ...   a = 33
   ...
   >>> p = patch('__main__.Something', autospec=SomethingForTest)
   >>> mock = p.start()
   >>> mock.a
   <NonCallableMagicMock name='Something.a' spec='int' id='...'>

[4] 이것은 클래스나 이미 인스턴스 화 된 객체에만 적용됩니다. 모킹된 클
    래스를 호출하여 모의 객체 인스턴스를 만드는 것은 실제 인스턴스를
    만들지 *않습니다*. ("dir()" 호출과 함께) 어트리뷰트 조회만 수행됩
    니다.


실링 모의 객체 봉인하기
-----------------------

unittest.mock.seal(mock)

   Seal은 봉인되는 모의 객체나 이것의 재귀적으로 이미 모의 객체인 어트
   리뷰트의 어트리뷰트를 액세스할 때 자동 모의 객체 생성을 비활성화합
   니다.

   이름이나 사양을 가진 모의 객체 인스턴스가 어트리뷰트에 대입되면 봉
   인 체인에서 고려되지 않습니다. 이것은 seal이 모의 객체의 일부를 고
   정하는 것을 방지할 수 있게 합니다.

      >>> mock = Mock()
      >>> mock.submock.attribute1 = 2
      >>> mock.not_submock = mock.Mock(name="sample_name")
      >>> seal(mock)
      >>> mock.new_attribute  # This will raise AttributeError.
      >>> mock.submock.attribute2  # This will raise AttributeError.
      >>> mock.not_submock.attribute2  # This won't raise.

   버전 3.7에 추가.
