--- tags: Python --- # Mock ## `MagicMock` vs `Mock` `MagicMock` 實作 `Mock` 類別絕大多數的 magic methods,**如果沒有需要實作 magic methods 的話,官方推薦直接使用 `MagicMock`**。 > `MagicMock` is a subclass of `Mock` with default implementations of most of the magic methods. You can use `MagicMock` without having to configure the magic methods yourself. ## spec 預設的 Mock 存取任何屬性、呼叫任何方法都會回傳 Mock。 ```python m = Mock() print(m.attribute) # <Mock name='mock.attribute' id='4517941776'> print(m.func()) # <Mock name='mock.func()' id='4461132944'> ``` 但這樣的行為表現可能就顯得不真實。如果嚴謹一點,可以使用 spec 來做規範,避免 Mock 呼叫到不屬於他的函式。 ```python class Person: def __init__(self): self._name = 'Celine' @property def name(self): return self._name ``` ```python m = Mock(spec=Person()) print(m.name) # <Mock name='mock.name' id='4519258384'> print(m.attribute) # AttributeError: Mock object has no attribute 'attribute' ``` 除了給與 class 外,也可以透過 array 的方式定義。 ```python m = Mock(spec=['name']) ``` 除了在 `Mock` 宣告外,也可以在 `patch` 使用,會與建立的 `Mock` 有相同的 spec。 ```python with patch('__main__.Person', spec=True) as m: m.name = 'Celine' person = Person() print(person.name) # Celine print(person.attribute) # AttributeError: Mock object has no attribute 'attribute' ``` ## Return value of child mocks 方便一點可以透過 dictionary 的方式設定個別的回傳值。 ```python m = Mock(**{'method.return_value': 3, 'other.side_effect': KeyError}) m.method() # 3 m.other() # raise KeyError ``` ## patch `patch` 可使用 decorator 的方式,以下為了方便才使用 context manager。 ### patch.dict 會以 update 的方式假造 dictionary,跳脫測試外時則恢復原狀。 ```python import os print(os.environ) # environ({'HOME': '/Users/celineyeh', 'LANG': 'en_US.UTF-8', ...}) with patch.dict('os.environ', {'HOME': '/NewHome'}) as m: print(os.environ) # environ({'HOME': '/NewHome', 'LANG': 'en_US.UTF-8', ...}) print(os.environ) # environ({'HOME': '/Users/celineyeh', 'LANG': 'en_US.UTF-8', ...}) ``` ## wraps 在 mock 的同時,照樣去執行原先的 function。 ```python m = Mock(wraps=Person()) m.greet() # Hi Celine m.mock_calls # [call.greet()] ```
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up