【问题标题】:Mocking a local variable of a function in python在python中模拟函数的局部变量
【发布时间】:2013-09-21 09:39:16
【问题描述】:

我是 python 模拟和单元测试的新手。如何模拟函数的局部变量?例如,如何在测试时将age 更改为 10 而不是 27?

# data_source.py
def get_name():
    age = 27 #real value
    return "Alice"

# person.py
from data_source import get_name

class Person(object):
    def name(self):
        return get_name()

# The unit test 
from mock import patch
from person import Person
   
@patch('person.age')
def test_name(mock_age):
    mock_age = 10 # mock value
    person = Person()
    name = person.name()
    assert age == 10

【问题讨论】:

  • 如果需要从外部更改age 值以测试函数,则设置该值不应成为函数工作的一部分。在这里,测试系统会自动警告您存在一个主要的代码设计问题。

标签: python unit-testing


【解决方案1】:

据我所知,mock 无法模拟局部变量。它只能模拟非本地对象。

试图模拟一个局部变量听起来很可疑。也许你应该尝试另一种方式。尝试将age 设为全局变量或类变量。然后你可以使用mock来模拟全局变量或者类变量。

如:

# source file
G_AGE = 27

def get_name():
    return "Alice"

# unit test file
...
@patch('XXX.G_AGE')
def test_name(mock_age):
    mock_age = 10
    ....

注意patch的用法:mock如果使用不当,可能无法正常工作。更多解释请参考Where to patch

【讨论】:

    【解决方案2】:

    我无法想象你为什么要这样做。测试是为了检查你的实际函数是否按照它们编写的方式工作,而不是改变它们的工作方式以匹配任意测试。

    无论如何,我怀疑你想传递一个带有默认值的参数:

    def get_values(age=27, name="Alice")
        ...
    

    【讨论】:

    • 你这么说,但这正是编写 mock 的原因:改变你的函数的工作方式,以便更容易/更快地测试。例如,我继承了很多与一些非常慢的 IO 交互的已发布 API 代码。我希望能够覆盖超时变量(我的被测函数中的本地和常量),这样我就可以测试异常行为而无需等待真实世界(5-7 分钟)的超时情况。跨度>
    • 您可能需要模拟从远程进程或 API 调用返回的变量的成功/失败。
    • @anregen “改变你的函数的工作方式”通过修改它的环境,而不是修改它自己的实现。您希望从外部修改超时值这一事实突出表明它是一个应该注入依赖项。如果你应该测试有问题的代码,你应该被允许修复它。如果不是,那么您正在测试使用执行 IO 的事物的客户端代码,并且您应该模拟整个事物,而不仅仅是它的超时值。即使在代码组织之外,您也不希望您的测试依赖于 IO 的成功!
    • @nmcilree 你可以通过模拟进程/调用本身来做到这一点,这样模拟会根据需要返回成功/失败。
    猜你喜欢
    • 2010-10-02
    • 1970-01-01
    • 2022-08-02
    • 1970-01-01
    • 2021-11-19
    • 1970-01-01
    • 1970-01-01
    • 2012-12-15
    相关资源
    最近更新 更多