Monkeypatching,對模塊和環境進行Mock
有時,測試需要調用依賴於全局設置的函數,或調用無法輕松測試的代碼(如網絡訪問)。 monkeypatch fixture可幫助你安全地設置/刪除屬性,字典項或環境變量,或修改sys.path以進行導入。 請參閱monkeypatch博客文章,了解一些介紹材料並討論其動機。
簡單示例如: 猴子補丁方法
如果你想阻止os.expanduser返回某個目錄,你可以在測試用例調用其之前,使用monkeypatch.setattr()方法改造這個函數:
# test_module.py文件內容
import os.path
def getssh(): # 偽應用代碼
return os.path.join(os.path.expanduser("~admin"),'.ssh')
def test_mytest(monkeypatch):
def mockreturn(path):
return '/abc'
monkeypatch.setattr(os.path,'expanduser',mockreturn)
x = getssh()
assert x == '/abc/.ssh'
這里在我們的測試用例中,使用猴子補丁改造了os.path.expanduser, 然后再進行調用。 測試執行完成后對os.path.expanduser修改將被撤消。
Monkeypatching 返回對象: 構建mock類
全局補丁示例如:阻止"requests"庫的遠程操作
如果要阻止"requests"庫在所有測試中執行http請求,你可以執行以下操作:
# conftest.py文件內容
import pytest
@pytest.fixture(autouse=True)
def no_requests(monkeypatch):
monkeypatch.delattr("requests.sessions.Session.request")
每個測試用例執行時都會自動使用該fixture,它將刪除測試用例內置屬性中的request.session.Session.request,以便在測試中任何使用requests庫創建http請求的用例都將失敗。
注意:
不建議使用猴子補丁改造Python內置函數,如open,compile等,因為它可能會破壞pytest的內部邏輯。 如果必須要使用,你可以通過參數:--tb = native,- tables = plain和--capture = no來試試,不一定不會有問題。
注意:
改造stdlib函數和pytest依賴的某些第三方庫本身可能會破壞pytest,因此在這些情況下,建議使用MonkeyPatch.context()來改造這些模塊:
import functools
def test_partial(monkeypatch):
with monkeypatch.context() as m:
m.setattr(functools,"partial",3)
assert functools.partial == 3
查看#3290號bug詳情
Monkeypatching 環境變量
Monkeypatching字典
參考API
查閱MonkeyPatch類相關文檔。
