"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" allows you to perform side effects, including raising an
exception when a mock is called:

>>> 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: <lambda>() takes exactly 3 arguments (1 given)

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

     If *spec* is an object (rather than a list of strings) then
     "__class__" returns the class of the spec object. This allows
     mocks to pass "isinstance()" tests.

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

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

   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.

      在 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

      This can be useful where you want to make a series of assertions
      that reuse the same object.

      *return_value* parameter when set to "True" resets
      "return_value":

         >>> mock = Mock(return_value=5)
         >>> mock('hello')
         5
         >>> mock.reset_mock(return_value=True)
         >>> mock('hello')
         <Mock name='mock()' id='...'>

      *side_effect* parameter when set to "True" resets "side_effect":

         >>> mock = Mock(side_effect=ValueError)
         >>> mock('hello')
         Traceback (most recent call last):
           ...
         ValueError
         >>> mock.reset_mock(side_effect=True)
         >>> mock('hello')
         <Mock name='mock()' id='...'>

      Note that "reset_mock()" *doesn't* clear the "return_value",
      "side_effect" or any child attributes you have set using normal
      assignment by default.

      Child mocks are reset as well.

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

   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__

      Normally the "__class__" attribute of an object will return its
      type. For a mock object with a "spec", "__class__" returns the
      spec class instead. This allows mock objects to pass
      "isinstance()" tests for the object they are replacing /
      masquerading as:

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

      "__class__" is assignable to, this allows a mock to pass an
      "isinstance()" check without forcing you to use a 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 上無意義。

Mock objects that use a class or an instance as a "spec" or "spec_set"
are able to pass "isinstance()" tests:

>>> 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.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 只被等待了一次並使用了指定的引數。

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


呼叫
----

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

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

If "side_effect" is set then it will be called after the call has been
recorded, so if "side_effect" raises an exception the call is still
recorded.

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

If "side_effect" is a function then whatever that function returns is
what calls to the mock return. The "side_effect" function is called
with the same arguments as the mock. This allows you to vary the
return value of the call dynamically, based on the input:

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

If you want the mock to still return the default return value (a new
mock), or any set return value, then there are two ways of doing this.
Either return "return_value" from inside "side_effect", or return
"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

To remove a "side_effect", and return to the default behaviour, set
the "side_effect" to "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

The "side_effect" can also be any iterable object. Repeated calls to
the mock will return values from the iterable (until the iterable is
exhausted and a "StopIteration" is raised):

>>> 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 物件會在需要時建立屬性。這使得它們可以假裝成任何種類的物件。

You may want a mock object to return "False" to a "hasattr()" call, or
raise an "AttributeError" when an attribute is fetched. You can do
this by providing an object as a "spec" for a mock, but that isn't
always convenient.

你可以通過刪除屬性來「阻擋」它們。一旦刪除，再次存取該屬性將會引發
"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 can be used as a "TestCase" class decorator. It works by
   decorating each test method in the class. This reduces the
   boilerplate code when your test methods share a common patchings
   set. "patch()" finds tests by looking for method names that start
   with "patch.TEST_PREFIX". By default this is "'test'", which
   matches the way "unittest" finds tests. You can specify an
   alternative prefix by setting "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* 設定成你想要的任何值。

To configure return values on methods of *instances* on the patched
class you must do this on the "return_value". For example:

   >>> 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 方法：啟動與停止
----------------------

All the patchers have "start()" and "stop()" methods. These make it
simpler to do patching in "setUp" methods or where you want to do
multiple patches without nesting decorators or with statements.

To use them call "patch()", "patch.object()" or "patch.dict()" as
normal and keep a reference to the returned "patcher" object. You can
then call "start()" to put the patch in place and "stop()" to undo it.

如果你使用 "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

A typical use case for this might be for doing multiple patches in the
"setUp" method of a "TestCase":

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

Now we want to test "some_function" but we want to mock out
"SomeClass" using "patch()". The problem is that when we import module
b, which we will have to do when it imports "SomeClass" from module a.
If we use "patch()" to mock out "a.SomeClass" then it will have no
effect on our test; module b already has a reference to the *real*
"SomeClass" and it looks like our patching had no effect.

關鍵是在使用（或查找它）的地方 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__',
    ...

Alternatively you can just use "vars(my_mock)" (instance members) and
"dir(type(my_mock))" (type members) to bypass the filtering
irrespective of "FILTER_DIR".


mock_open
---------

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

   用於建立取代 "open()" 用途的 mock 的輔助函式。它適用於直接呼叫或用
   作情境管理器的 "open()"。

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

   *read_data* is a string for the "read()", "readline()", and
   "readlines()" methods of the file handle to return.  Calls to those
   methods will take data from *read_data* until it is depleted.  The
   mock of these methods is pretty simplistic: every time the *mock*
   is called, the *read_data* is rewound to the start.  If you need
   more control over the data that you are feeding to the tested code
   you will need to customize this mock for yourself.  When that is
   insufficient, one of the in-memory filesystem packages on PyPI can
   offer a realistic filesystem for testing.

   在 3.4 版的變更: Added "readline()" and "readlines()" support. The
   mock of "read()" changed to consume *read_data* rather than
   returning it on each call.

   在 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（自動規格）
------------------------

Autospeccing is based on the existing "spec" feature of mock. It
limits the api of mocks to the api of an original object (the spec),
but it is recursive (implemented lazily) so that attributes of mocks
only have the same api as the attributes of the spec. In addition
mocked functions / methods have the same call signature as the
original so they raise a "TypeError" if they are called incorrectly.

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

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

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

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

"unittest.mock" already provides a feature to help with this, called
speccing. If you use a class or instance as the "spec" for a mock then
you can only access attributes on the mock that exist on the real
class:

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

You can see that "request.Request" has a spec. "request.Request" takes
two arguments in the constructor (one of which is *self*). Here's what
happens if we try to call it incorrectly:

   >>> 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" objects are not callable, so the return value of
instantiating our mocked out "request.Request" is a non-callable mock.
With the spec in place any typos in our asserts will raise the correct
error:

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


Order of precedence of "side_effect", "return_value" and *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
