嘲笑使用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" 

然后嘲笑补丁正确。