"unittest.mock" — mock 物件函式庫
*********************************

在 3.3 版被加入.

**原始碼：**Lib/unittest/mock.py

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

"unittest.mock" 在 Python 中是一個用於進行測試的函式庫。 它允許你用
mock 物件在測試中替換部分系統，並判定它們是如何被使用的。

"unittest.mock" 提供了一個以 "Mock" 為核心的類別，去除在測試中建立大量
stubs 的需求。 在執行動作之後，你可以判定哪些 method （方法）／屬性被
使用，以及有哪些引數被呼叫。 你還可以用常規的方式指定回傳值與設定所需
的屬性。

此外，mock 還提供了一個 "patch()" 裝飾器，用於 patching 測試範圍內對
module（模組）以及 class（類別）級別的屬性，以及用於建立唯一物件的
"sentinel"。有關如何使用 "Mock"、"MagicMock" 和 "patch()" 的一些範例，
請參閱快速導引。

Mock 被設計用於與 "unittest" 一起使用，並且基於 「action（操作） ->
assertion（判定）」 模式，而不是許多 mocking 框架使用的 「record（記錄
） -> replay（重播）」 模式。

對於早期版本的 Python，有一個 backport（向後移植的）"unittest.mock" 可
以使用，可從 PyPI 下載 mock。


快速導引
========

"Mock" 和 "MagicMock" 物件在你存取它們時建立所有屬性和 method（方法）
，並儲存它們如何被使用的詳細訊息。你可以配置它們，以指定回傳值或限制可
用的屬性，然後對它們的使用方式做出判定：

>>> 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" 允許你執行 side effects，包含在 mock 被呼叫時引發例外：

>>> from unittest.mock import Mock
>>> 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* 引數可以配
置 mock ，讓其從另一個物件獲取規格。嘗試讀取 mock 中不存在於規格中的屬
性或方法將會失敗，並出現 "AttributeError"。

"patch()" 裝飾器／情境管理器可以在測試中簡單的 mock 模組中的類別或物件
。被指定的物件在測試期間會被替換為 mock（或其他物件），並在測試結束時
恢復：

   >>> 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 裝飾器時，mock 傳遞到被裝飾函式的順序會跟其被應用
  的順序相同（一般 *Python* 應用裝飾器的順序）。這意味著由下而上，因此
  在上面的範例中，"module.ClassName1" 的 mock 會先被傳入。使用
  "patch()" 時，需注意的是你得在被查找物件的命名空間中（in the
  namespace where they are looked up）patch 物件。這通常很直接，但若需
  要快速導引，請參閱該 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()"，用於在測試範圍中設定 dictionary（字典）內的值，並
在測試結束時將其恢復為原始狀態：

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

Mock 支援對 Python 的魔術方法的 mocking。最簡單使用魔術方法的方式是使
用 "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'

為了確保測試中的 mock 物件與它們要替換的物件具有相同的 api，你可以使用
自動規格。自動規格（auto-speccing）可以通過 patch 的 *autospec* 引數或
"create_autospec()" 函式來完成。自動規格建立的 mock 物件與它們要替換的
物件具有相同的屬性和方法，並且任何函式和方法（包括建構函式）都具有與真
實物件相同的呼叫簽名（call signature）。

這可以確保如果使用方法錯誤，你的 mock 會跟實際程式碼以相同的方式失敗：

>>> 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: missing a required argument: 'b'

"create_autospec()" 也可以用在類別上，它複製了 "__init__" 方法的簽名，
它也可以用在可呼叫物件上，其複製了 "__call__" 方法的簽名。


Mock 類別
=========

"Mock" 是一個彈性的的 mock 物件，旨在代替程式碼中 stubs 和 test
doubles （測試替身）的使用。Mock 是可呼叫的，並在你存取它們時將屬性建
立為新的 mock [1]。存取相同的屬性將永遠回傳相同的 mock。Mock 記錄了你
如何使用它們，允許你判定你的程式碼對 mock 的行為。

"MagicMock" 是 "Mock" 的子類別，其中所有魔術方法均已預先建立並可供使用
。也有不可呼叫的變體，在你 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*：這可以是字串的 list（串列），也可以是充當 mock 物件規格的
     現有物件（類別或實例）。如果傳入一個物件，則通過對該物件呼叫 dir
     來形成字串的串列（不包括不支援的魔術屬性和方法）。存取不在此串列
     中的任何屬性都會引發 "AttributeError"。

     如果 *spec* 是一個物件（而不是一個字串的串列），那麼 "__class__"
     會回傳 spec 物件的類別。這允許 mocks 通過 "isinstance()" 測試。

   * *spec_set*：*spec* 的一個更嚴格的變體。如果使用 *spec_set*，在
     mock 上嘗試 *set* 或取得不在傳遞給 *spec_set* 的物件上的屬性將會
     引發 "AttributeError"。

   * *side_effect*：每當呼叫 Mock 時要呼叫的函式，參見 "side_effect"
     屬性，用於引發例外或動態變更回傳值。該函式使用與 mock 相同的引數
     呼叫，且除非它回傳 "DEFAULT"，否則此函式的回傳值將用作回傳值。

     *side_effect* 也可以是一個例外的類別或實例。在這種情況下，當呼叫
     mock 時，該例外將被引發。

     如果 *side_effect* 是一個可疊代物件，那麼對 mock 的每次呼叫將回傳
     可疊代物件中的下一個值。

     *side_effect* 可以通過將其設置為 "None" 來清除。

   * *return_value*：當呼叫 mock 時回傳的值。預設情況下，這是一個新的
     Mock（在首次存取時建立）。參見 "return_value" 屬性。

   * *unsafe*：預設情況下，存取任何以 *assert*、*assret*、*asert*、
     *aseert* 或 *assrt* 開頭的屬性將引發 "AttributeError"。如果傳遞
     "unsafe=True"，將會允許存取這些屬性。

     在 3.5 版被加入.

   * *wraps*：被 mock 物件包裝的項目。如果 *wraps* 不是 "None"，那麼呼
     叫 Mock 將通過被包裝的物件（回傳真實結果）。存取 mock 的屬性將會
     回傳一個 Mock 物件，該物件包裝了被包裝物件的對應屬性（因此嘗試存
     取不存在的屬性將引發 "AttributeError"）。

     如果 mock 已經明確設定了 *return_value*，那麼呼叫並不會被傳遞到被
     包裝的物件，而是回傳已設定好的 *return_value*。

   * *name*：如果 mock 有一個名稱，那麼它會被用於 mock 的 repr。這對於
     除錯很有用。此名稱將被傳播到子 mocks。

   Mocks 還可以使用任意的關鍵字引數進行呼叫。這些關鍵字引數將在建立
   mock 之後用於設定 mock 的屬性。欲知更多，請參見 "configure_mock()"
   方法。

   assert_called()

      確認 mock 至少被呼叫一次。

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

      在 3.6 版被加入.

   assert_called_once()

      確認 mock 只被呼叫一次。

      >>> 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.
      Calls: [call(), call()].

      在 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 = 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.
      Calls: [call('foo', bar='baz'), call('other', bar='values')].

   assert_any_call(*args, **kwargs)

      斷言 mock 已經被使用指定的引數呼叫。

      這個斷言在 mock 曾經被呼叫過時通過，不同於
      "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)

      斷言 mock 已經使用指定的呼叫方式來呼叫。此斷言會檢查
      "mock_calls" 串列中的呼叫。

      如果 *any_order* 為 false，那麼這些呼叫必須按照順序。在指定的呼
      叫之前或之後可以有額外的呼叫。

      如果 *any_order* 為 true，那麼這些呼叫可以以任何順序出現，但它們
      必須全部出現在 "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()

      斷言 mock 從未被呼叫。

      >>> 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.
      Calls: [call()].

      在 3.5 版被加入.

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

      reset_mock 方法重置 mock 物件上的所有呼叫屬性：

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

      在 3.6 版的變更: reset_mock 函式新增了兩個僅限關鍵字引數
      (keyword-only arguments)。

      這在你想要進行一系列重複使用同一物件的斷言時非常有用。請注意，預
      設情況下，"reset_mock()" *不會*清除 "return_value"、
      "side_effect" 或使用普通賦值設定的任何子屬性。如果你想要重置
      "return_value" 或 "side_effect"，則將相應的參數設置為 "True"。
      Child mock 和回傳值 mock（如果有的話）也會被重置。

      備註:

        *return_value* 和 *side_effect* 是僅限關鍵字引數。

   mock_add_spec(spec, spec_set=False)

      向 mock 增加一個規格 (spec)。*spec* 可以是一個物件或一個字串串列
      (list of strings)。只有在 *spec* 上的屬性才能作為 mock 的屬性被
      取得。

      如果 *spec_set* 為 true，那麼只能設定在規格中的屬性。

   attach_mock(mock, attribute)

      將一個 mock 作為這個 Mock 的屬性附加，取代它的名稱和上代
      (parent)。對附加的 mock 的呼叫將被記錄在這個 Mock 的
      "method_calls" 和 "mock_calls" 屬性中。

   configure_mock(**kwargs)

      透過關鍵字引數在 mock 上設定屬性。

      可以在使用 method（方法）呼叫時，使用標準點記法 (dot notation)
      並將字典拆開，為 child mock 設定屬性、回傳值和 side effects：

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

      同樣的事情可以在 mock 的建構函式呼叫中實現：

      >>> 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()" 的存在是為了在 mock 被建立後更容易進行組態設
      定。

   __dir__()

      "Mock" 物件限制了 "dir(some_mock)" 僅顯示有用的結果。對於具有
      *spec* 的 mock，這包含所有被允許的 mock 屬性。

      請參閱 "FILTER_DIR" 以了解這種過濾行為的作用，以及如何關閉它。

   _get_child_mock(**kw)

      建立為了得到屬性和回傳值的 child mock。預設情況下，child mock 將
      與其上代是相同的型別。Mock 的子類別可能會想要置換此行為，以自定
      義 child mock 的建立方式。

      對於不可呼叫的 mock，將使用可呼叫的變體，而不是任何的自定義子類
      別。

   called

      一個 boolean（布林），表述 mock 物件是否已經被呼叫：

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

   call_count

      一個整數，告訴你 mock 物件被呼叫的次數：

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

   return_value

      設定此值以配置呼叫 mock 時回傳的值：

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

      預設的回傳值是一個 mock 物件，你也可以按照正常的方式配置它：

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

      這可以是一個在呼叫 mock 時要呼叫的函式、一個可疊代物件，或者要引
      發的例外（類別或實例）。

      如果你傳遞一個函式，它將被呼叫，其引數與 mock 相同，且除非該函式
      回傳 "DEFAULT" 單例 (singleton)，否則對 mock 的呼叫將回傳函式回
      傳的任何值。如果函式回傳 "DEFAULT"，那麼 mock 將回傳其正常的回傳
      值（從 "return_value" 得到）。

      如果你傳遞一個可疊代物件，它將被用於檢索一個疊代器，該疊代器必須
      在每次呼叫時產出 (yield) 一個值。這個值可以是要引發的例外實例，
      或者是對 mock 呼叫時要回傳的值（處理 "DEFAULT" 的方式與函式的狀
      況相同）。

      以下是一個引發例外的 mock 的範例（用於測試 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" 可以在建構函式中設定。以下是一個範例，它將 mock 被
      呼叫時給的值加一並回傳：

      >>> 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"（如果 mock 尚未被呼叫），或是 mock 上次被呼叫時使
      用的引數。這將以元組的形式呈現：第一個成員 (member)，其可以通過
      "args" 屬性訪問，是 mock 被呼叫時傳遞的所有有序引數（或一個空元
      組）。第二個成員，其可以通過 "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"，以及串列 "call_args_list"、"method_calls" 和
      "mock_calls" 的成員都是 "call" 物件。這些都是元組，因此可以解包
      以獲取各個引數並進行更複雜的斷言。參見 calls as tuples。

      在 3.8 版的變更: 新增 "args" 與 "kwargs" 特性。

   call_args_list

      這是按順序列出所有呼叫 mock 物件的串列（因此串列的長度表示它被呼
      叫的次數）。在任何呼叫發生之前，它會是一個空的串列。 "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" 物件。這些物件可以被拆包為元
      組，以取得各個引數。參見 calls as tuples。

   method_calls

      除了追蹤對自身的呼叫之外，mock 還會追蹤對方法和屬性的呼叫，以及*
      它們（這些方法和屬性）*的方法和屬性：

      >>> 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" 物件。這些物件可以拆包為元組，
      以取得各個引數。參見 calls as tuples。

   mock_calls

      "mock_calls" 記錄了 *所有* 對 mock 物件的呼叫，包含其方法、魔術
      方法以及回傳值 mock。

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

      "method_calls" 的成員都是 "call" 物件。這些物件可以拆包為元組，
      以取得各個引數。參見 calls as tuples。

      備註:

        "mock_calls" 記錄的方式意味著在進行巢狀呼叫時，上代 (ancestor)
        呼叫的參數不會被記錄，因此在比較時它們將始終相等：

        >>> 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"
      的 mock 物件，"__class__" 會回傳 spec 的類別。這允許 mock 物件通
      過對它們所替代或偽裝的物件進行的 "isinstance()" 測試：

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

      "__class__" 可以被指定，這允許 mock 通過 "isinstance()" 檢查，而
      不需要強制使用 spec：

      >>> 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* 在不可呼叫的 mock 上無意義。

使用類別或實例作為 "spec" 或 "spec_set" 的 mock 物件能夠通過
"isinstance()" 測試：

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

"Mock" 類別支援 mock 魔術方法。細節請參考魔術方法。

Mock類別和 "patch()" 裝飾器於組態時接受任意的關鍵字引數。對於
"patch()" 裝飾器，這些關鍵字會傳遞給正在建立 mock 的建構函式。這些關鍵
字引數用於配置 mock 的屬性：

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

Child mock 的回傳值和 side effect 可以使用使用點記法進行設置。由於你無
法直接在呼叫中使用帶有點 (.) 的名稱，因此你必須建立一個字典並使用 "**"
解包：

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

在匹配對 mock 的呼叫時，使用 *spec*（或 *spec_set*）建立的可呼叫 mock
將會內省 (introspect) 規格物件的簽名 (signature)。因此，它可以匹配實際
呼叫的引數，無論它們是按位置傳遞還是按名稱傳遞：

   >>> 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()"。在使用 Autospeccing（自動
規格） 時，它還適用於 mock 物件的方法呼叫。

在 3.4 版的變更: 對於已經設置了規格（spec）和自動規格（autospec）的
mock 物件，新增簽名內省功能。

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

   一個理應在類別上當成 "property" 或其他 *descriptor* 的 mock。
   "PropertyMock" 提供了 "__get__()" 和 "__set__()" 方法，因此你可以在
   它被提取時指定回傳值。

   從物件中提取 "PropertyMock" 實例會不帶任何引數呼叫 mock。設定它則會
   用設定的值來呼叫 mock：

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

由於 mock 屬性的儲存方式，你無法直接將 "PropertyMock" 附加到 mock 物件
。但是你可以將其附加到 mock 型別的物件：

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

警示:

  If an "AttributeError" is raised by "PropertyMock", it will be
  interpreted as a missing descriptor and "__getattr__()" will be
  called on the parent mock:

     >>> m = MagicMock()
     >>> no_attribute = PropertyMock(side_effect=AttributeError)
     >>> type(m).my_property = no_attribute
     >>> m.my_property
     <MagicMock name='mock.my_property' id='140165240345424'>

  詳情請見 "__getattr__()"。

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

   "MagicMock" 的非同步版本。"AsyncMock" 物件的表現將被視為非同步函式
   ，並且呼叫的結果是一個可等待物件。

   >>> 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"（如果上
   代 mock 為 "AsyncMock" 或 "MagicMock"）或 "Mock"（如果上代 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()

      斷言 mock 至少被等待過一次。請注意這與物件是否被呼叫是分開的，
      "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 正好被等待了一次。

      >>> mock = AsyncMock()
      >>> async def main():
      ...     await mock()
      ...
      >>> asyncio.run(main())
      >>> mock.assert_awaited_once()
      >>> asyncio.run(main())
      >>> mock.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 await not found.
      Expected: mock('other')
      Actual: mock('foo', bar='bar')

   assert_awaited_once_with(*args, **kwargs)

      斷言 mock 只被等待了一次並使用了指定的引數。

      >>> 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 曾經被使用指定的引數等待過。

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

      斷言 mock 已被使用指定的呼叫進行等待。"await_args_list" 串列將被
      檢查以確認等待的內容。

      如果 *any_order* 為 false，則等待必須按照順序。指定的等待之前或
      之後可以有額外的呼叫。

      如果 *any_order* 為 true，則等待可以以任何順序出現，但它們必須全
      部出現在 "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 從未被等待。

      >>> 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 物件已被等待的次數。

      >>> 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 尚未被等待），或者是上次等待 mock 時
      使用的引數。與 "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 物件所有等待的串列（因此串列的長度表示
      該物件已被等待的次數）。在進行任何等待之前，此串列為空。

      >>> 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')]

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

   A version of "MagicMock" for multithreading tests. The
   "ThreadingMock" object provides extra methods to wait for a call to
   be invoked, rather than assert on it immediately.

   The default timeout is specified by the "timeout" argument, or if
   unset by the "ThreadingMock.DEFAULT_TIMEOUT" attribute, which
   defaults to blocking ("None").

   You can configure the global default timeout by setting
   "ThreadingMock.DEFAULT_TIMEOUT".

   wait_until_called(*, timeout=UNSET)

      Waits until the mock is called.

      If a timeout was passed at the creation of the mock or if a
      timeout argument is passed to this function, the function raises
      an "AssertionError" if the call is not performed in time.

      >>> mock = ThreadingMock()
      >>> thread = threading.Thread(target=mock)
      >>> thread.start()
      >>> mock.wait_until_called(timeout=1)
      >>> thread.join()

   wait_until_any_call_with(*args, **kwargs)

      Waits until the mock is called with the specified arguments.

      If a timeout was passed at the creation of the mock the function
      raises an "AssertionError" if the call is not performed in time.

      >>> mock = ThreadingMock()
      >>> thread = threading.Thread(target=mock, args=("arg1", "arg2",), kwargs={"arg": "thing"})
      >>> thread.start()
      >>> mock.wait_until_any_call_with("arg1", "arg2", arg="thing")
      >>> thread.join()

   DEFAULT_TIMEOUT

      Global default timeout in seconds to create instances of
      "ThreadingMock".

   在 3.13 版被加入.


呼叫
----

Mock 物件可被呼叫。呼叫將回傳設定為 "return_value" 屬性的值。預設的回
傳值是一個新的 Mock 物件；它會在第一次存取回傳值時（無論是顯式存取還是
透過呼叫 Mock）被建立，但是這個回傳值會被儲存，之後每次都回傳同一個值
。

對物件的呼叫會被記錄在如 "call_args" 和 "call_args_list" 等屬性中。

如果 "side_effect" 被設定，那麼在呼叫被記錄後它才會被呼叫，所以如果
"side_effect" 引發例外，呼叫仍然會被記錄。

呼叫 mock 時引發例外的最簡單方式是將 "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" 是一個函式，則該函式回傳的東西就是對 mock 的呼叫所
回傳的值。"side_effect" 函式會使用與 mock 相同的引數被呼叫。這讓你可以
根據輸入動態地變更呼叫的回傳值：

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

如果你希望 mock 仍然回傳預設的回傳值（一個新的 mock），或者是任何已設
定的回傳值，有兩種方法可以實現。從 "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" 也可以是任何可疊代的物件。對 mock 的重複呼叫將從可疊代物
件中回傳值（直到疊代物件耗盡並引發 "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


刪除屬性
--------

Mock 物件會在需要時建立屬性。這使得它們可以假裝成任何種類的物件。

你可能希望一個 mock 物件在 "hasattr()" 呼叫時回傳 "False"，或者在屬性
被提取時引發 "AttributeError"。你可以通過將物件提供為 mock 的 "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


Mock 名稱與名稱屬性
-------------------

由於 "name" 是傳遞給 "Mock" 建構函式的引數，如果你想讓你的 mock 物件擁
有 "name" 屬性，你不能在建立時直接傳遞它。有兩種替代方法。其中一個選擇
是使用 "configure_mock()"：

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

更簡單的方法是在 mock 建立後直接設定 "name" 屬性：

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


如同屬性一般附加 mock
---------------------

當你將一個 mock 附加為另一個 mock 的屬性（或作為回傳值），它將成為該
mock 的「子代 (child)」。對子代的呼叫將被記錄在上代的 "method_calls"
和 "mock_calls" 屬性中。這對於配置子代並將它們附加到上代，或將 mock 附
加到記錄所有對子代的呼叫的上代並允許你對 mock 間的呼叫順序進行斷言非常
有用：

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

如果 mock 有 name 引數，則上述規則會有例外。這使你可以防止「親屬關係
(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()" 為你建立的 mock 會自動被賦予名稱。若要將具有名稱的 mock
附加到上代，你可以使用 "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 物件時，會讓直譯器*
    非常*困惑。如果你需要魔術方法的支援，請參閱魔術方法。


Patchers
========

patch 裝飾器僅用於在裝飾的函式範圍內對物件進行 patch。它們會自動為你處
理 patch 的中止，即使有異常被引發也是如此。所有這些函式也可以在 with
陳述式中使用，或者作為類別裝飾器使用。


patch
-----

備註:

  關鍵是要在正確的命名空間進行 patch。請參閱 where to patch 一節。

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

   "patch()" 充當函式裝飾器、類別裝飾器或情境管理器。在函式或 with 陳
   述式的內部，*目標*會被 patch 成一個*新的*物件。當函式或 with 陳述式
   結束時，patch 就會被解除。

   如果 *new* 被省略，則如果被 patch 的物件是非同步函式，目標會被替換
   為 "AsyncMock"，反之則替換為 "MagicMock"。如果 "patch()" 做為裝飾器
   使用且省略了 *new*，則所建立的 mock 會作為額外的引數傳遞給被裝飾的
   函式。如果 "patch()" 作為情境管理器使用，則所建立的 mock 將由情境管
   理器回傳。

   *target* 應該是以 "'package.module.ClassName'" 形式出現的字串。
   *target* 會被引入並用 *new* 物件替換指定的物件，因此 *target* 必須
   可從你呼叫 "patch()" 的環境中引入。target 在執行被裝飾的函式時被引
   入，而不是在裝飾器作用時 (decoration time)。

   *spec* 和 *spec_set* 關鍵字引數會傳遞給 "MagicMock"，如果 patch 正
   在為你建立一個。

   此外，你還可以傳遞 "spec=True" 或 "spec_set=True"，這將導致 patch
   將被 mock 的物件作為 spec/spec_set 物件傳遞。

   *new_callable* 允許你指定一個不同的類別或可呼叫的物件，用於被呼叫並
   建立 *new* 物件。預設情況下，對於非同步函式使用 "AsyncMock"，而對於
   其他情況則使用 "MagicMock"。

   *spec* 的一種更強大的形式是 *autospec*。如果你設定 "autospec=True"
   ，則該 mock 將使用被替換物件的規格來建立。該 mock 的所有屬性也將具
   有被替換物件的對應屬性的規格。被 mock 的方法和函式將檢查其引數，如
   果呼叫時引數與規格不符（被使用錯誤的簽名 (signature) 呼叫），將引發
   "TypeError"。對於替換類別的 mock，它們的回傳值（即 'instance'）將具
   有與類別相同的規格。請參閱 "create_autospec()" 函式和 Autospeccing
   （自動規格）。

   你可以用 "autospec=some_object" 替代 "autospec=True"，以使用任意物
   件作為規格，而不是被替換的物件。

   預設情況下，"patch()" 將無法取代不存在的屬性。如果你傳入
   "create=True"，且屬性不存在，則當被 patch 的函式被呼叫時，patch 將
   為你建立該屬性，並在被 patch 的函式結束後再次刪除它。這對於撰寫針對
   你的生產程式碼在執行環境建立的屬性的測試時非常有用。此功能預設為關
   閉，因為這可能會相當危險。開啟這個功能後，你可以對於實際上不存在的
   API 撰寫會通過的測試！

   備註:

     在 3.5 版的變更: 如果你正在 patch 模組中的內建函式，那麼你不需要
     傳遞 "create=True"，它預設會被加入。

   patch 可以做為 "TestCase" 類別的裝飾器使用。它透過裝飾類別中的每個
   測試方法來運作。當你的測試方法共享一組常見的 patch 時，這會減少繁冗
   的代碼。"patch()" 通過搜尋以 "patch.TEST_PREFIX" 開頭的方法名來尋找
   測試。預設情況下會是 "'test'"，這與 "unittest" 尋找測試的方式相匹配
   。你可以通過設定 "patch.TEST_PREFIX" 來指定別的前綴。

   透過 with 陳述式，Patch 可以做為情境管理器使用。patch 適用於 with
   陳述式之後的縮排區塊。如果你使用 "as"，則被 patch 的物件將被綁定到
   "as" 後面的名稱；如果 "patch()" 正在為你建立一個 mock 物件，這會非
   常有用。

   "patch()" 接受任意的關鍵字引數。如果被 patch 的物件是非同步的，這些
   將會被傳遞給 "AsyncMock"，如果是同步的則會傳遞給 "MagicMock"，或如
   果指定了 *new_callable*，則傳遞給它。

   "patch.dict(...)"、"patch.multiple(...)" 和 "patch.object(...)" 可
   用於其餘的使用情境。

"patch()" 作為函式裝飾器，為你建立 mock 並將其傳遞給被裝飾的函式：

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

Patch 一個類別會以 "MagicMock" *實例*取代該類別。如果該類別在被測試的
程式碼中實例化，那麼它將是會被使用的 mock 的 "return_value"。

如果該類別被實例化多次，你可以使用 "side_effect" 來每次回傳一個新的
mock。 或者你可以將 *return_value* 設定成你想要的任何值。

若要配置被 patch 的類別的*實例*方法的回傳值，你必須在 "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()" 正在取代一個*類別*，那麼
被建立的 mock 的回傳值將具有相同的規格。：

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

當你想要為被建立的 mock 使用一個替代的類別取代預設的 "MagicMock" 時，
*new_callable* 引數非常有用。例如，如果你想要一個 "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()" 為你建立 mock 時，通常你需要做的第一件事就是配置 mock。其
中一些配置可以在對 patch 的呼叫中完成。你傳遞到呼叫中的任何關鍵字都將
用於在被建立的 mock 上設定屬性：

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

除了被建立的 mock 上的屬性外，還可以配置 child mock 的 "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

預設情況下，嘗試 patch 模組中不存在的函式（或類別中的方法或屬性）將會
失敗，並引發 "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_attribute'

但是在對 "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()" 現在會回傳一個
"AsyncMock"。


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

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

   使用一個 mock 物件 patch 一個物件（*目標*）上的命名成員（*屬性*）。

   "patch.object()" 可以做為裝飾器、類別裝飾器或情境管理器使用。引數
   *new*、*spec*、*create*、*spec_set*、*autospec* 和 *new_callable*
   與在 "patch()" 中的引數具有相同的意義。與 "patch()" 一樣，
   "patch.object()" 接受任意關鍵字引數來配置它所建立的 mock 物件。

   當作為類別裝飾器使用時，"patch.object()" 會遵循 "patch.TEST_PREFIX"
   來選擇要包裝的方法。

你可以使用三個引數或兩個引數來呼叫 "patch.object()"。三個引數的形式接
受要被 patch 的物件、屬性名稱和要替換掉屬性的物件。

當使用兩個引數的形式呼叫時，你會省略要替換的物件，一個 mock 會為你建立
並將其作為額外的引數傳遞給被裝飾的函式：

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

   Patch 字典或類字典的物件，並在測試後將字典回復到其原本的狀態。

   *in_dict* 可以是一個字典或一個類對映的容器。如果它是一個對映，那麼
   它至少必須支援獲取、設定、刪除項目以及對鍵的疊代。

   *in_dict* 也可以是指定字典名稱的字串，然後透過 import 來取得該字典
   。

   *values* 可以是要設定的值的字典。*values* 也可以是 "(key, value)"
   對 (pairs) 的可疊代物件。

   如果 *clear* 為 true，則在設定新值之前字典將被清除。

   也可以使用任意關鍵字引數呼叫 "patch.dict()" 以在字典中設定值。

   在 3.8 版的變更: "patch.dict()" 現在在做為情境管理器使用時回傳被
   patch 的字典。

"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" 來
告知 patcher 使用不同的前綴。請參閱 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)

   在一次呼叫中執行多個 patch。它接受被 patch 的物件（作為物件或透過
   import 取得物件的字串）和 patch 的關鍵字引數：

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

   如果你想要 "patch.multiple()" 為你建立 mock，請使用 "DEFAULT" 作為
   值。在這種情況下，被建立的 mock 會透過關鍵字傳遞到被裝飾的函式中，
   並且當 "patch.multiple()" 作為情境管理器時會回傳字典。

   "patch.multiple()" 可以做為裝飾器、類別裝飾器或情境管理器使用。引數
   *spec*、*spec_set*、*create*、*autospec* 和 *new_callable* 與在
   "patch()" 中的引數具有相同的意義。這些引數將應用於由
   "patch.multiple()" 完成的*所有* patch。

   當作為類別裝飾器使用時，"patch.multiple()" 遵循 "patch.TEST_PREFIX"
   來選擇要包裝的方法。

如果你想要 "patch.multiple()" 為你建立 mock，那麼你可以使用 "DEFAULT"
作為值。如果你使用 "patch.multiple()" 作為裝飾器，那麼被建立的 mock 將
透過關鍵字傳遞到被裝飾的函式中。：

   >>> 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()" 作為情境管理器使用，則情境管理器回傳的值是一個
字典，其中被建立的 mock 會按名稱作為其鍵值：

   >>> 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
   ...


patch 方法：啟動與停止
----------------------

所有的 patcher 都有 "start()" 與 "stop()" 方法。這使得在 "setUp" 方法
中進行 patch 或在你想要在沒有巢狀使用裝飾器或 with 陳述式的情況下進行
多個 patch 時變得更簡單。

要使用它們，請像平常一樣呼叫 "patch()"、"patch.object()" 或
"patch.dict()" ，並保留對回傳的 "patcher" 物件的參照。之後你就可以呼叫
"start()" 將 patch 準備就緒，並呼叫 "stop()" 來取消 patch。

如果你使用 "patch()" 為你建立 mock，那麼它將透過呼叫 "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" 方法中執行多個 patch：

   >>> 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" 來 "取消" patch。這可
  能會比你想像的還要複雜一點，因為如果有例外在 "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。

patch.stopall()

   停止所有運作的 patch。只停止以 "start" 啟動的 patch。


patch 內建函式
--------------

你可以 patch 模組內的任何內建函式。以下範例 patch 內建函式 "ord()"：

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


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

所有 patcher 都可以作為類別裝飾器使用。以這種方式使用時，它們包裝了類
別上的每個測試方法。Patcher 將 "'test'" 開頭的方法認定為測試方法。這與
"unittest.TestLoader" 預設尋找測試方法的方式相同。

你可能會想為你的測試使用不同的前綴。你可以透過設定 "patch.TEST_PREFIX"
來告知 patcher 使用不同的前綴：

   >>> 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 裝飾器
---------------------

如果你想執行多個 patch，那麼你可以簡單地堆疊裝飾器。

你可以使用這個模式來堆疊多個 patch 裝飾器：

>>> @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')

請注意，裝飾器是從底部向上應用的。這是 Python 應用裝飾器的標準方式。被
建立的 mock 傳遞到測試函式中的順序與此順序相同。


該 patch 何處
-------------

"patch()" 的工作原理是（暫時）將 *name* 指向的物件變更為另一個物件。可
以有許多 name 指向任何單一物件，因此為了使 patch 起作用，你必須確保你
patch 了被測試系統使用的 name。

基本原則是在物件*被查找*的位置進行 patch，該位置不一定與其被定義的位置
相同。幾個範例將有助於闡明這一點。

想像一下，我們想要測試一個專案，其結構如下：

   a.py
       -> Defines SomeClass

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

現在我們想要測試 "some_function"，但我們想使用 "patch()" mock
"SomeClass"。問題是，當我們 import 模組 b 時（我們必須這樣做），它會從
模組 a import "SomeClass"。如果我們使用 "patch()" 來 mock
"a.SomeClass"，那麼它對我們的測試就不會有任何影響；模組 b 已經有了一個
*真實的* "SomeClass" 的參照 ，看起來我們的 patch 並沒有任何效果。

關鍵是在使用（或查找它）的地方 patch "SomeClass"。在這個情況下，
"some_function" 實際上會在我們 import 它的模組 b 中查找 "SomeClass"。
這裡的 patch 應該長得像這樣：

   @patch('b.SomeClass')

然而，考慮另一種情況，其中模組 b 並不是使用 "from a import SomeClass"
，而是 "import a"，然後 "some_function" 使用 "a.SomeClass"。這兩種
import 形式都很常見。在這種情況下，我們想要 patch 的類別正在其模組中被
查找，因此我們必須 patch "a.SomeClass"：

   @patch('a.SomeClass')


Patch 描述器與代理物件 (Proxy Objects)
--------------------------------------

patch 和 patch.object 都正確地 patch 和還原描述器：類別方法、靜態方法
以及屬性。你應該在 *類別* 而不是實例上 patch 它們。它們還可以使用代理
屬性存取的*一些*物件，例如 django 設定物件。


MagicMock 以及魔術方法支援
==========================


Mock 魔術方法
-------------

"Mock" 支援 mock Python 協定方法，其也被稱作 *"魔術方法"*。這允許 mock
物件替換容器或實作 Python 協定的其他物件。

由於魔術方法被查找的方式與一般的方法 [2] 不同，因此專門實作了此支援方
式。這代表著僅有特定的魔術方法被此方式支援。現在已支援清單中已經*幾乎*
包含了所有魔術方法。如果你需要 mock 任何魔術方法而其尚未被支援，請讓我
們知道。

你可以透過將你感興趣的方法設定為函式或 mock 實例來 mock 魔術方法。如果
你使用函式，那麼它*必須*將 "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()
>>> 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*關鍵字引數來建立一個 mock，則嘗試設定規格中未包含的
  魔術方法將引發一個 "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__"

* 數值方法（包括右側 (right hand) 和原地 (in-place) 變體）："__add__"
  、"__sub__"、"__mul__"、"__matmul__"、"__truediv__"、"__floordiv__"
  、"__mod__"、"__divmod__"、"__lshift__"、"__rshift__"、"__and__"、
  "__xor__"、"__or__" 和 "__pow__"

* 數值轉換方法："__complex__"、"__int__"、"__float__" 和 "__index__"

* 描述器方法："__get__"、"__set__" 和 "__delete__"

* Pickling："__reduce__"、"__reduce_ex__"、"__getinitargs__"、
  "__getnewargs__"、"__getstate__" 和 "__setstate__"

* 檔案系統路徑表示法："__fspath__"

* 非同步疊代方法："__aiter__" 和 "__anext__"

在 3.8 版的變更: 新增對於 "os.PathLike.__fspath__()" 的支援。

在 3.8 版的變更: 新增對於 "__aenter__"、"__aexit__"、"__aiter__" 和
"__anext__" 的支援。

以下方法存在，但「不」被支援，因為它們在被 mock 使用時，會無法動態設定
，或可能導致問題：

* "__getattr__"、"__setattr__"、"__init__" 和 "__new__"

* "__prepare__"、"__instancecheck__"、"__subclasscheck__"、"__del__"


Magic Mock
----------

"MagicMock" 有兩個變體："MagicMock" 和 "NonCallableMagicMock"。

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

   "MagicMock" 是 "Mock" 的子類別，其預設具有大多數*魔術方法*的實作。
   你可以使用 "MagicMock"，而無需自行配置魔術方法。

   建構函式參數的意義與 "Mock" 中的參數相同。

   如果你使用 *spec* 或 *spec_set* 引數，那麼*只有*規格中存在的魔術方
   法會被建立。

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

   "MagicMock" 的不可呼叫版本。

   建構函式參數的意義與 "MagicMock" 中的參數相同，但 *return_value* 和
   *side_effect* 除外，它們對不可呼叫的 mock 來說沒有任何意義。

魔術方法是使用 "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__"：mock 的預設雜湊

* "__str__"：mock 的預設字串

* "__sizeof__"：mock 的預設 sizeof

舉例來說：

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

"__eq__()" 和 "__ne__()" 這兩個相等的方法是特別的。它們使用
"side_effect" 屬性對識別性 (identity) 進行預設的相等比較，除非你變更它
們的回傳值以回傳其他內容：

   >>> 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__"

[2] 魔術方法*應該*在類別而不是實例上被查找。不同版本的 Python 對於這條
    規則的適用並不一致。支援的協定方法應適用於所有支援的 Python 版本。

[3] 該函式基本上與類別掛鉤，但每個 "Mock" 實例都與其他實例保持隔離。


輔助函式
========


sentinel（哨兵）
----------------

unittest.mock.sentinel

   "哨兵"物件提供了一種為你的測試提供獨特物件的便利方式。

   當你使用名稱存取屬性時，屬性會根據需要被建立。存取相同的屬性將始終
   回傳相同的物件。回傳的物件會具有合適的 repr，讓測試失敗的訊息是可閱
   讀的。

   在 3.7 版的變更: "哨兵"屬性現在當被"複製"或"序列化"時會保留其識別性
   。

在測試時，有時你需要測試特定物件是否作為引數被傳遞給另一個方法或回傳。
建立命名的哨兵物件來測試這一點是常見的。"sentinel" 提供了一種此類建立
和測試物件識別性的便利方式。

在這個例子中，我們 monkey patch "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
>>> result
sentinel.some_object


DEFAULT
-------

unittest.mock.DEFAULT

   "DEFAULT" 物件是一個預先建立的哨兵（實際上是 "sentinel.DEFAULT"）。
   它可以被 "side_effect" 函式使用來表示正常的回傳值應該被使用。


call
----

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

   與 "call_args"、"call_args_list"、"mock_calls" 和 "method_calls" 相
   比，"call()" 是一個用於進行更簡單的斷言的輔助物件。"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 物件，"call_list()" 回傳所有中間呼叫以及最
   終呼叫的串列。

"call_list" 在對「鍊接呼叫 (chained calls)」進行斷言時特別有用。鍊接呼
叫是在單行程式碼進行的多次呼叫。這會導致 mock 上的 "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" 物件是（位置引數
, 關鍵字引數）的二元組，而 "Mock.mock_calls" 中的 "call" 物件以及你自
己建立的 "call" 物件是（名稱, 位置引數, 關鍵字引數）的三元組。

你可以利用它們作為元組的特性來提取單個引數，以進行更複雜的內省和斷言。
位置引數是一個元組（如果沒有位置引數則為空元組），關鍵字引數是一個字典
：

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

   使用另一個物件作為規格建立一個 mock 物件。Mock 上的屬性將使用
   *spec* 物件上的對應屬性作為其規格。

   被 mock 的函式或方法將檢查其引數，以確保他們被使用正確的簽名來呼叫
   。

   如果 *spec_set* 為 "True"，則嘗試設定規格物件上不存在的屬性將引發
   "AttributeError"。

   如果一個類別作為規格使用，則 mock（該類別的實例）的回傳值將具有相同
   的規格。你可以透過傳遞 "instance=True" 來使用一個類別作為一個實例物
   件的規格。只有當 mock 的實例是可呼叫物件時，回傳的 mock 才會是可呼
   叫物件。

   "create_autospec()" 也接受任意的關鍵字引數，這些引數會傳遞給已建立
   的 mock 的建構函式。

請參閱 Autospeccing（自動規格） 以得知如何以 "create_autospec()" 使用
自動規格以及如何在 "patch()" 中使用 *autospec* 引數的範例。

在 3.8 版的變更: 如果目標是一個非同步函式，"create_autospec()" 現在會
回傳一個 "AsyncMock"。


ANY
---

unittest.mock.ANY

有時你可能需要對 mock 的呼叫中的*某些*引數進行斷言，但你不在意其他的某
些引數，或想將它們單獨從 "call_args" 中取出並進行更加複雜的斷言。

要忽略某些引數，你可以傳入對*所有物件*來說都相等的物件。那麼無論傳入什
麼內容，對 "assert_used_with()" 和 "assert_used_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

"ANY" 不只能與呼叫物件比較，其也可以在測試斷言中使用：

   class TestStringMethods(unittest.TestCase):

       def test_split(self):
           s = 'hello world'
           self.assertEqual(s.split(), ['hello', ANY])


FILTER_DIR
----------

unittest.mock.FILTER_DIR

"FILTER_DIR" 是一個模組級別的變數，用於控制 mock 物件回應 "dir()" 的方
式。其預設值為 "True"，它使用以下描述的過濾方式來只顯示有用的成員。如
果你不喜歡這個過濾方式，或由於診斷意圖而需要將其關閉，請設定
"mock.FILTER_DIR = False"。

當過濾方式開啟時，"dir(some_mock)" 僅會顯示有用的屬性，並將包括通常不
會顯示的任何動態建立的屬性。如果 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" 來說是私有的，而不是被 mock 的東西）底線和
雙底線前綴屬性已從在 "Mock" 上呼叫 "dir()" 的結果中濾除。如果你不喜歡
這種特性，可以透過設定模組級別開關 "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()" 用途的 mock 的輔助函式。它適用於直接呼叫或用
   作情境管理器的 "open()"。

   *mock* 引數是要配置的 mock 物件。如果其為 "None"（預設值），那麼就
   會為你建立一個 "MagicMock"，其 API 限制在標準檔案處理上可用的方法或
   屬性。

   *read_data* 是檔案處理方法 "read()"、"readline()" 和 "readlines()"
   的回傳字串。對這些方法的呼叫將從 *read_data* 取得資料，直到資料耗盡
   。對這些方法的 mock 非常單純：每次呼叫 *mock* 時，*read_data* 都會
   倒回到起點。如果你需要對提供給測試程式碼的資料進行更多控制，你會需
   要自行客製化這個 mock。如果這樣還不夠，PyPI 上的其中一個記憶體內檔
   案系統 (in-memory filesystem) 套件可以提供用於測試的真實檔案系統。

   在 3.4 版的變更: 新增對 "readline()" 和 "readlines()" 的支援。
   "read()" 的 mock 更改為消耗 *read_data* 而不是在每次呼叫時回傳它。

   在 3.5 版的變更: 現在，每次呼叫 *mock* 時都會重置 *read_data*。

   在 3.8 版的變更: 新增 "__iter__()" 到實作中，以便使疊代（例如在 for
   迴圈中）正確地消耗 *read_data*。

使用 "open()" 作為情境管理器是確保檔案處理正確關閉的好方式，且這種方式
正在變得普遍：

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

問題是，即使你 mock 了對 "open()" 的呼叫，它也是作為情境管理器使用的*
回傳物件*（且其 "__enter__()" 和 "__exit__()" 已被呼叫）。

使用 "MagicMock" mock 情境管理器相當常見並且精細，因此輔助函式就非常有
用：

   >>> 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'


Autospeccing（自動規格）
------------------------

自動規格以 mock 現有的 "spec" 功能作為基礎。它將 mock 的 api 限制為原
始物件（規格）的 api，但它是遞迴的（惰性 (lazily) 實現），因此 mock 的
屬性僅具有與規格的屬性相同的 api。此外，被 mock 的函式/方法具有與原始
的函式/方法相同的呼叫簽名，因此如果它們被不正確地呼叫，就會引發
"TypeError"。

在解釋自動規格如何運作之前，我們先解釋為什麼需要它。

"Mock" 是一個非常強大且靈活的物件，但它有一個常見的 mock 缺陷。如果你
重構某些程式碼或重新命名成員等，則任何仍然使用*舊 api* 但使用 mock 而
非真實物件的程式碼測試仍然會通過。這意味著即使你的程式碼壞了，但測試仍
可以全部通過。

在 3.5 版的變更: 在 3.5 之前，當測試應該引發錯誤時，斷言單字中存在拼字
錯誤的測驗會默默地通過。你仍可以透過將 "unsafe=True" 傳遞給 Mock 來實
作此行為。

謹記這是你需要有整合測試和單元測試的另一個原因。單獨測試所有內容都很好
，但如果你不測試你的單元是如何「連接在一起」的，那麼測試還是有機會發現
很多錯誤。

"mock" 已經提供了一個功能來幫助解決這個問題，其稱為 speccing。如果你使
用類別或實例作為 mock 的 "spec"，那麼你在 mock 上只能存取真實類別中存
在的屬性：

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

該規格僅適用於 mock 本身，因此在 mock 上的任何方法仍然有相同的問題：

   >>> mock.has_data()
   <mock.Mock object at 0x...>
   >>> mock.has_data.assret_called_with()  # 故意的錯字！

自動規格解決了這個問題。你可以將 "autospec=True" 傳遞給 "patch()" /
"patch.object()" 或使用 "create_autospec()" 函式建立帶有規格的 mock。
如果你對 "patch()" 使用 "autospec=True" 引數，則被取代的物件將作為規格
物件使用。因為規格是「惰性」完成的（規格是在 mock 被存取時作為屬性被建
立的），所以你可以將它與非常複雜或深度巢狀使用的物件（例如連續引用的模
組）一起使用，而不會過於影響性能。

這是一個正在使用的例子：

   >>> 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" 有一個規格。"request.Request" 在建構函式
中接受兩個引數（其中之一是 *self*）。如果我們錯誤地呼叫它，會發生以下
情況：

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

此規格也適用於實例化的類別（即有規格的 mock 的回傳值）：

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

"Request" 物件不是可呼叫物件，因此實例化我們 mock out 的
"request.Request" 的回傳值是不可呼叫的 mock。規格到位後，斷言中的任何
拼字錯誤都會引發正確的錯誤：

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

在許多情況下，你只需要將 "autospec=True" 新增至現有的 "patch()" 呼叫中
，然後就可以防止因拼字錯誤和 api 變更而導致的錯誤。

除了透過 "patch()" 使用 *autospec* 之外，還有一個 "create_autospec()"
用於直接建立有自動規格的 mock：

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

然而，這並非完全沒有限制，這就是為什麼它不是預設的行為。為了理解規格物
件上有哪些可用屬性，autospec 必須內省（存取屬性）規格。當你遍歷 mock
上的屬性時，原始物件的對應遍歷正在默默發生。如果你的規格物件具有可以觸
發程式碼執行的屬性或描述器，那麼你可能無法使用 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'

有幾種不同的方法可以解決這個問題。最簡單但可能有點煩人的方法是在建立後
簡單地在 mock 上設定所需的屬性。因為雖然 *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" 作為規格*永遠不會*有用，並且可能表示通常
屬於其他型別的成員，因此自動規格不會對設定為 "None" 的成員使用規格。這
些會只是普通的 mock（通常是 MagicMocks）：

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

如果修改正式生產 (production) 類別以新增預設值不符合你的喜好，那麼還有
更多選擇。其中之一就是簡單地使用實例作為規格而不是使用類別。另一種是建
立一個正式生產類別的子類別，並將預設值新增至子類別中，而不影響正式生產
類別。這兩個都需要你使用替代物件作為規格。值得慶幸的是 "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] 這只適用於類別或已經實例化的物件。呼叫一個被 mock 的類別來建立一個
    mock 實例*不會*建立真的實例。它僅查找屬性及對 "dir()" 的呼叫。


密封 mock
---------

unittest.mock.seal(mock)

   當存取被密封的 mock 的屬性或其任何已經遞迴 mock 的屬性時，seal 將停
   用 mock 的自動建立。

   如果將具有名稱或規格的 mock 實例指派給屬性，則不會出現在密封鏈中。
   這表示可藉由固定 mock 物件的一部分來防止密封。：

      >>> 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 版被加入.


"side_effect"、"return_value" 和 *wraps* 的優先順序
===================================================

它們的優先順序是：

1. "side_effect"

2. "return_value"

3. *wraps*

如果這三個都有設定，mock 將會回傳來自 "side_effect" 的值，並忽略
"return_value" 和被包裝物件。如果設定了任兩項，則優先順序較高的一項將
回傳該值。無論先設定哪個順序，優先順序都保持不變。

>>> from unittest.mock import Mock
>>> class Order:
...     @staticmethod
...     def get_value():
...         return "third"
...
>>> order_mock = Mock(spec=Order, wraps=Order)
>>> order_mock.get_value.side_effect = ["first"]
>>> order_mock.get_value.return_value = "second"
>>> order_mock.get_value()
'first'

由於 "None" 是 "side_effect" 的預設值，如果將其值重新賦值回為 "None"，
則會檢查 "return_value" 和被包裝物件之間的優先順序，忽略 "side_effect"
。

>>> order_mock.get_value.side_effect = None
>>> order_mock.get_value()
'second'

如果 "side_effect" 回傳的值是 "DEFAULT"，它將被忽略，並且優先順序被移
動到後面一個以獲得要回傳的值。

>>> from unittest.mock import DEFAULT
>>> order_mock.get_value.side_effect = [DEFAULT]
>>> order_mock.get_value()
'second'

當 "Mock" 包裝一個物件時，"return_value" 的預設值將為 "DEFAULT"。

>>> order_mock = Mock(spec=Order, wraps=Order)
>>> order_mock.return_value
sentinel.DEFAULT
>>> order_mock.get_value.return_value
sentinel.DEFAULT

優先順序將忽略該值，並將移動到最後一個，即被包裝物件。

當對被包裝物件進行真正的呼叫時，建立此 mock 的實例將回傳該類別的真實實
例。必須傳遞被包裝物件所需的位置引數（如果存在）。

>>> order_mock_instance = order_mock()
>>> isinstance(order_mock_instance, Order)
True
>>> order_mock_instance.get_value()
'third'

>>> order_mock.get_value.return_value = DEFAULT
>>> order_mock.get_value()
'third'

>>> order_mock.get_value.return_value = "second"
>>> order_mock.get_value()
'second'

但如果你為其賦予 "None" 則不會被忽略，因為它是明確賦值。因此，優先順序
不會移至被包裝物件。

>>> order_mock.get_value.return_value = None
>>> order_mock.get_value() is None
True

即使你在初始化 mock 時同時設定所有三個，優先順序也保持不變：

>>> order_mock = Mock(spec=Order, wraps=Order,
...                   **{"get_value.side_effect": ["first"],
...                      "get_value.return_value": "second"}
...                   )
...
>>> order_mock.get_value()
'first'
>>> order_mock.get_value.side_effect = None
>>> order_mock.get_value()
'second'
>>> order_mock.get_value.return_value = DEFAULT
>>> order_mock.get_value()
'third'

如果 "side_effect" 已耗盡，則優先順序將不會使值由後面取得。相反地這會
引發 "StopIteration" 例外。

>>> order_mock = Mock(spec=Order, wraps=Order)
>>> order_mock.get_value.side_effect = ["first side effect value",
...                                     "another side effect value"]
>>> order_mock.get_value.return_value = "second"

>>> order_mock.get_value()
'first side effect value'
>>> order_mock.get_value()
'another side effect value'

>>> order_mock.get_value()
Traceback (most recent call last):
 ...
StopIteration
