如何用mock修补模块的内部函数?

2024-04-25

我所说的“内部函数”是指从定义它的同一模块内调用的函数。

我正在使用mock http://www.voidspace.org.uk/python/mock/图书馆,特别是patch http://www.voidspace.org.uk/python/mock/patch.html装饰器,在我的单元测试中。它们是 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

有谁知道模拟是否可以修补像这样内部使用的函数,或者我运气不好?


答案:清理你该死的进口

@patch('mymodule.TAX_LOCATION', '')确实适当地修补了一些东西,但是由于我们当时的导入非常随意——有时我们会导入mymodule.build_cart,有时我们导入project.mymodule.build_cart--“完全”导入的实例根本没有修补。无论如何,在没有明确告知的情况下,不能期望 Mock 了解两个单独的导入路径。

从那时起,我们已经在更长的路径上标准化了所有导入,现在事情表现得好多了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何用mock修补模块的内部函数? 的相关文章

随机推荐