[Python] 在 pytest 裡 monkey patch 系統內建的函式
今天在用 pytest 寫 unit-testing 程式時,遇到一個問題:
要如何 mock 掉 python 原本就提供的內建函式呢?
平常如果是像 urllib.quote() 這種函式,可以用下面的方法來 mock:
def test_mock(monkeypatch): def mock_urllib_quote(s, safe="/"): # Do something... return "mocked result" # Mock set_system_info import urllib monkeypatch.setattr(urllib, "quote", mock_urllib_quote) assert urllib.quote("abc") == "mocked result"
不過,如果我今天想要 mock 的是像 open() 這種內建函式呢?
在用 open() 前,好像不用 import 某個特定模組…
後來在網路上找到了解答,原來 open() 這類的內建函式是屬於 __builtin__ 模組的,
所以只要去 mock __builtin__ 模組就行囉~
def test_mock_open(monkeypatch): # Mock open() import __builtin__ monkeypatch.setattr(__builtin__, "open", mock_open) f = open("test") assert f.read() == "" assert f.fileno() == 0
這邊定義了一個 mock_open(),我讓它傳回一個自己定義的 MockFileObj,
然後在裡面定義我想要的檔案讀寫行為:
class MockFileObj(object): data = "" def __init__(self): pass def __enter__(self): return self def __exit__(self, exit_type, msg, traceback): pass def read(self): return MockFileObj.data def readlines(self, size=0): return [] def write(self, data): MockFileObj.data += data print "write [%s]" % (data) def fileno(self): return 0 def close(self): pass def mock_open(name, *args, **kwargs): return MockFileObj()
參考資料:
pytest: Monkeypatching/mocking modules and environments
Mock python builtin functions in pytest
(本頁面已被瀏覽過 1,324 次)