嘲笑使用python模拟function
我想模拟一个函数(返回一些外部内容)使用python模拟模块(http://www.voidspace.org.uk/python/mock/index.html)。
我有一些麻烦嘲笑导入到模块的function。
例如,在util.py我有
def get_content(): return "stuff"
我想嘲笑util.get_content,以便它返回别的东西。
我正在尝试这个:
util.get_content=Mock(return_value="mocked stuff")
如果get_content
被另一个模块调用,它实际上似乎不会返回模拟对象。 我错过了如何使用模拟的东西?
请注意,如果我调用以下,事情正常工作:
>>> 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
可能是在这里指责,因为它不指向模拟function。
我想我有一个解决办法,但我仍然不清楚如何解决一般情况
在mymodule中,如果我replace
from util import get_content class MyObj: def func(): get_content()
同
import util class MyObj: def func(): util.get_content()
模拟似乎被调用。 看起来像命名空间需要匹配(这是有道理的)。 不过,奇怪的是我期望的
import mymodule mymodule.get_content = mock.Mock(return_value="mocked stuff")
在我使用from / import语法(现在将get_content引入到mymodule中)的原始案例中执行这个技巧。 但是这仍然是指unmocked get_content。
结果是名字空间很重要 – 编写代码时只需要牢记这一点。
您必须修补正在使用的function。 在你的情况下,将在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
创build你的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"
请注意,只要在util.get_content
之前评估foobar
就可以从任意位置导入foobar(模块A导入导入foobar的B)。
一般的情况是使用mock
patch
。 考虑以下:
utils.py
def get_content(): return 'stuff'
mymodule.py
from util import get_content class MyClass(object): def func(self): return get_content()
test.py
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
中使用它。
上面已经用模拟v2.0.0,nosetests v1.3.7和python v2.7.9进行了testing。
虽然它没有直接提供你的问题的答案,但另一种可能的select是使用@staticmethod将你的函数转换为静态方法。
所以你可以使用类似的东西把你的模块utils转换成一个类:
class util(object): @staticmethod def get_content(): return "stuff"
然后嘲笑补丁正确。