[英]Mocking Functions Using Python Mock
我正在嘗試使用 python mock 模塊Mock
一個函數(返回一些外部內容)。
我在模擬導入模塊的函數時遇到了一些麻煩。
例如,在util.py
我有
def get_content():
return "stuff"
我想模擬util.get_content
以便它返回其他內容。
我正在嘗試這個:
util.get_content=Mock(return_value="mocked stuff")
如果get_content
在另一個模塊內被調用,它實際上似乎從未返回模擬對象。 我在如何使用Mock
方面缺少一些東西嗎?
請注意,如果我調用以下內容,則一切正常:
>>> util.get_content=Mock(return_value="mocked stuff")
>>> util.get_content()
"mocked stuff"
但是,如果從另一個模塊內部調用get_content
,它將調用原始函數而不是模擬版本:
>>> from mymodule import MyObj
>>> util.get_content=Mock(return_value="mocked stuff")
>>> m=MyObj()
>>> m.func()
"stuff"
mymodule.py
內容
from util import get_content
class MyObj:
def func():
get_content()
所以我想我的問題是 - 如何從我調用的模塊內部調用函數的 Mocked 版本?
看來from module import function
可能是這里的罪魁禍首,因為它沒有指向 Mocked 函數。
我想我有一個解決方法,雖然它仍然不太清楚如何解決一般情況
在mymodule
,如果我更換
from util import get_content
class MyObj:
def func():
get_content()
和
import util
class MyObj:
def func():
util.get_content()
Mock
似乎被調用了。 看起來命名空間需要匹配(這是有道理的)。 然而,奇怪的是,我期望
import mymodule
mymodule.get_content = mock.Mock(return_value="mocked stuff")
在我使用 from/import 語法(現在將get_content
拉入mymodule
)的原始情況下做這個技巧。 但這仍然是指未模擬的get_content
。
原來命名空間很重要 - 只需要在編寫代碼時記住這一點。
一般情況是使用mock
patch
。 考慮以下:
實用程序.py
def get_content():
return 'stuff'
我的模塊.py
from util import get_content
class MyClass(object):
def func(self):
return get_content()
測試文件
import unittest
from mock import patch
from mymodule import MyClass
class Test(unittest.TestCase):
@patch('mymodule.get_content')
def test_func(self, get_content_mock):
get_content_mock.return_value = 'mocked stuff'
my_class = MyClass()
self.assertEqual(my_class.func(), 'mocked stuff')
self.assertEqual(get_content_mock.call_count, 1)
get_content_mock.assert_called_once()
請注意get_content
是如何get_content
的,它不是util.get_content
,而是mymodule.get_content
因為我們在mymodule
中使用它。
以上已經用 mock v2.0.0、nosetests v1.3.7 和 python v2.7.9 進行了測試。
您必須修補正在使用的函數。 在您的情況下,這將在 mymodule 模塊中。
import mymodule
>>> mymodule.get_content = Mock(return_value="mocked stuff")
>>> m = mymodule.MyObj()
>>> m.func()
"mocked stuff"
這里的文檔中有一個參考: http : //docs.python.org/dev/library/unittest.mock.html#where-to-patch
假設您正在模塊foobar
創建模擬:
import util, mock
util.get_content = mock.Mock(return_value="mocked stuff")
如果您導入mymodule
並調用util.get_content
而不先導入foobar
,則不會安裝您的模擬:
import util
def func()
print util.get_content()
func()
"stuff"
反而:
import util
import foobar # substitutes the mock
def func():
print util.get_content()
func()
"mocked stuff"
注意, foobar
可以從任何地方(模塊A導入B,其進口取得foobar),只要可以導入foobar
前計算util.get_content
被調用。
雖然它沒有直接為您的問題提供答案,但另一種可能的替代方法是使用 @staticmethod 將您的函數轉換為靜態方法。
因此,您可以使用以下內容將模塊 utils 轉換為類:
class util(object):
@staticmethod
def get_content():
return "stuff"
然后模擬正確地修補它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.