模拟 function/object 和基于 input/conditions 的 return 值
Mocking a function/object, and return values based on input/conditions
我面临以下情况。
我有以下源码
#file:[src/my_module.py]
def order_names(unordered_input: List) -> str:
# function that orders a list of names
...
if(is_ID(unordered_input[i])):
id = unordered_input[i]
name = get_name_by_id(id)
...
def get_name_by_id(id) -> str:
# function that returns a name, based on an ID, through a Rest API call
return make_some_network_call(id)
我想测试函数 order_names
,我想模拟对 get_name_by_id(id)
的调用。
假设 get_name_by_id(id)
将针对各种 id
多次调用,是否可以根据输入创建一个 returns 值的模拟?
例如:
#file:[test/test_my_module.py]
from unittest import mock
from my_module import order_names
@mock.patch("src.my_module.get_name_by_id", return_value={"3": "Mark", "4": "Kate", "5":"Alfred"})
def test_order_names():
ordered_names = order_names(["3", "4", "Suzan", "5"])
assert ordered_names == "Alfred, Kate, Mark, Suzan"
以上测试代码是要实现的行为类型的示例,因为 get_name_by_id()
不是 dict
return 类型。
干杯!
您基本上需要 get_name_by_id
的替代实现,而不仅仅是新的 return 值。
# Adjust the definition to behave the same when the lookup fails
def get_name_locally(id):
return {"3": "Mark", "4": "Kate", "5":"Alfred"}.get(id)
def test_order_names():
with mock.patch('src.my_module.get_name_by_id', get_name_locally):
ordered_names = order_names(["3", "4", "Suzan", "5"])
assert ordered_names = "Alfred, Kate, Mark, Suzan"
如果 get_name_by_id
更复杂,您也可以考虑修补网络调用,让 get_name_by_id
运行 保持原样。
# The same as get_name_locally above, but only because
# get_name_by_id and make_some_network_call are functionally
# identical as far as the question is written.
def network_replacement(id):
return {"3": "Mark", "4": "Kate", "5":"Alfred"}.get(id)
def test_order_names():
with mock.patch('src.my_module.make_some_network_call', network_replacement):
ordered_names = order_names(["3", "4", "Suzan", "5"])
assert ordered_names = "Alfred, Kate, Mark, Suzan"
现在,当您调用 order_names
时,它会调用 get_name_by_id
,get_name_by_id
将使用您对 make_some_network_call
的替代定义。
我面临以下情况。
我有以下源码
#file:[src/my_module.py]
def order_names(unordered_input: List) -> str:
# function that orders a list of names
...
if(is_ID(unordered_input[i])):
id = unordered_input[i]
name = get_name_by_id(id)
...
def get_name_by_id(id) -> str:
# function that returns a name, based on an ID, through a Rest API call
return make_some_network_call(id)
我想测试函数 order_names
,我想模拟对 get_name_by_id(id)
的调用。
假设 get_name_by_id(id)
将针对各种 id
多次调用,是否可以根据输入创建一个 returns 值的模拟?
例如:
#file:[test/test_my_module.py]
from unittest import mock
from my_module import order_names
@mock.patch("src.my_module.get_name_by_id", return_value={"3": "Mark", "4": "Kate", "5":"Alfred"})
def test_order_names():
ordered_names = order_names(["3", "4", "Suzan", "5"])
assert ordered_names == "Alfred, Kate, Mark, Suzan"
以上测试代码是要实现的行为类型的示例,因为 get_name_by_id()
不是 dict
return 类型。
干杯!
您基本上需要 get_name_by_id
的替代实现,而不仅仅是新的 return 值。
# Adjust the definition to behave the same when the lookup fails
def get_name_locally(id):
return {"3": "Mark", "4": "Kate", "5":"Alfred"}.get(id)
def test_order_names():
with mock.patch('src.my_module.get_name_by_id', get_name_locally):
ordered_names = order_names(["3", "4", "Suzan", "5"])
assert ordered_names = "Alfred, Kate, Mark, Suzan"
如果 get_name_by_id
更复杂,您也可以考虑修补网络调用,让 get_name_by_id
运行 保持原样。
# The same as get_name_locally above, but only because
# get_name_by_id and make_some_network_call are functionally
# identical as far as the question is written.
def network_replacement(id):
return {"3": "Mark", "4": "Kate", "5":"Alfred"}.get(id)
def test_order_names():
with mock.patch('src.my_module.make_some_network_call', network_replacement):
ordered_names = order_names(["3", "4", "Suzan", "5"])
assert ordered_names = "Alfred, Kate, Mark, Suzan"
现在,当您调用 order_names
时,它会调用 get_name_by_id
,get_name_by_id
将使用您对 make_some_network_call
的替代定义。