【发布时间】:2011-07-17 12:04:18
【问题描述】:
“内部函数”是指从定义它的同一模块中调用的函数。
我在单元测试中使用mock 库,特别是patch 装饰器。它们是 Django 单元测试,但这应该适用于任何 python 测试。
我有一个具有多个功能的模块,其中许多功能相互调用。例如(虚构代码,忽略缺少的decimal.Decimal):
TAX_LOCATION = 'StateName, United States'
def add_tax(price, user):
tax = 0
if TAX_LOCATION == 'StateName, UnitedStates':
tax = price * .75
return (tax, price+tax)
def build_cart(...):
# build a cart object for `user`
tax, price = add_tax(cart.total, cart.user)
return cart
这些是更深层调用链的一部分(func1 -> func2 -> build_cart -> add_tax),所有这些都在同一个模块中。
在我的单元测试中,我想禁用税收以获得一致的结果。正如我所看到的,我的两个选项是 1)修补 TAX_LOCATION(例如,使用空字符串)以便 add_tax 实际上不做任何事情或 2)修补 add_tax 以简单地返回(0,价格)。
但是,当我尝试修补其中任何一个时,补丁似乎在外部工作(我可以在测试中导入修补的部分并将其打印出来,得到预期值),但在内部似乎没有效果(结果我从代码中获取的行为就像未应用补丁一样)。
我的测试是这样的(又是虚构的代码):
from mock import patch
from django.test import TestCase
class MyTests(TestCase):
@patch('mymodule.TAX_LOCATION', '')
def test_tax_location(self):
import mymodule
print mymodule.TAX_LOCATION # ''
mymodule.func1()
self.assertEqual(cart.total, original_price) # fails, tax applied
@patch('mymodule.add_tax', lambda p, u: (0, p))
def test_tax_location(self):
import mymodule
print mymodule.add_tax(50, None) # (0, 50)
mymodule.func1()
self.assertEqual(cart.total, original_price) # fails, tax applied
有谁知道 mock 是否可以像这样修补内部使用的函数,还是我不走运?
【问题讨论】:
-
测试函数中的任何导入都会看到修补后的值,但我怀疑问题仍然是“命名空间”问题。 (即修补的位置和它们的使用位置不匹配)。你没有显示真正的代码 - mymodule.func1() 没有显示,也没有显示“cart”来自哪里 - 所以我无法诊断问题(我是 mock 的作者)。跨度>
-
@fuzzyman,具有讽刺意味的是,到目前为止,我在尝试生成一个重现问题的简短示例时完全没有成功(我在简单的 python 模块和简单的 django 项目中都尝试了几件事,一切都按预期运行)。不过,我在其中使用的项目是一个非常庞大的 django 项目,所以在这一点上,我相信导入时会发生一些受污染的事情(从这里的示例,从 build_cart 中,
print sys.modules['app.views'].add_tax打印一个 Mock 对象而print add_tax打印原始函数)。