如何在python中模拟多个函数?

时间:2013-09-22 05:36:18

标签: python

我是python中单元测试和模拟的新手,在下面的场景我知道如何模拟没有任何参数mock exampleget_name(),但我无法模仿下面以age为参数的场景。你能帮我修一下下面的模拟test_name功能吗?

# data_source.py
def get_name(a):
    return "Alice"+str(a)

def get_age():
    return 30

Person类公开了一个从数据源中提取数据的方法:

# person.py
from data_source import get_name

class Person(object):
    def name(self):
        age = get_age()
        return get_name(age)    

from mock import patch
from person import Person

@patch('person.get_name')
def test_name(mock_get_name):
    mock_get_name.return_value = "Bob"
    person = Person()
    name = person.name()
    assert name == "Bob"

提前致谢!

1 个答案:

答案 0 :(得分:0)

首先,除了导入get_name之外,您还需要导入get_age,因为您在Person类中使用它。其次,没有像person.get_name那样定义的东西。所以你无法修补它。相反,您可能想要修补data_souce.get_name

但不幸的是,这不起作用,因为data_source是一个python模块,而get_name是其中要重新定义的方法。例如,如果get_nameDataSource类中的方法,则补丁装饰器会很好。我不知道它为什么不起作用的确切原因,因为我没有深入研究模拟库的实现细节,但是库的意图与你想要使用它的方式不同。

要解决此问题,您可以将data_source转换为类,或者您可以通过为其分配不同的函数或lambda来临时更改名称get_name的含义:

import data_source

def test_person():
    # replace the function
    data_source._real_get_name = data_source.get_name
    data_source.get_name=lamba a: "Bob"
    # do some work
    person = Person()
    name = person.name()
    # after use of the get_name function, put the original function back
    data_source.get_name=data_source._real_get_name
    # assert post condition
    assert name=="Bob"

当然,更改哪些功能会严重影响您的程序,并且应该小心,可能仅用于测试。即使出现意外错误,也要确保始终将原始功能恢复原状。