我有一个模拟api调用的函数,如下所示:
def mocked_api_call(animal = animal, soundtype=soundtype)
output = make_sound(animal, soundtype)
return output
目标是让模拟在第二次使用相同的参数集调用时返回不同的输出。例如,我希望第一次调用返回“喵”,第二次返回“ MEAAAOWWW”,而第三次调用返回“喵”,就像这样:
output = mocked_api_call(animal='cat', soundtype = 'meow')
# outputs 'meow'
output = mocked_api_call(animal='cat', soundtype = 'meow')
# outputs 'MEAAAOWWW'
output = mocked_api_call(animal='cat', soundtype = 'meow')
# outputs 'mew'
补丁用于测试使用调用api的函数的父函数:
def parent_function(**kwargs):
response = make_sound(animal=animal, soundtype=soundtype)
通过猴子补丁调用测试功能,如下所示:
@mock.patch('myscript.api_call', side_effect=mocked_api_call)
def test_parent_function(*args, **kwargs):
output = parent_function(**kwargs)
但是我找不到一种方法来生成依赖于函数被调用多少次的响应。你可以用pytest做这件事吗?
答案 0 :(得分:1)
我不确定您的测试外观如何,但让我们假设您要使用不同的测试,在每个测试中都会重置调用索引。根据您的需要,以下内容可能对您来说太通用了-如果您只需要将索引传递给make_sound
,就可以了。
from unittest import mock
import pytest
class TestSounds:
indexes = {}
sounds = {
('cat', 'meow'): ('meow', 'MEAAAOWWW', 'mew'),
}
@classmethod
def make_sound(cls, animal, soundtype):
key = (animal, soundtype)
if key in cls.sounds:
index = cls.indexes.setdefault(key, 0)
sound = cls.sounds[key][index]
cls.indexes[key] = (index + 1) % len(cls.sounds[key])
return sound
# if you need the order not be reset in each test, you can change
# the scope to "class"
@pytest.fixture(scope="function", autouse=True)
def reset_indexes(self):
self.__class__.indexes = {}
def test_parent_function(self, **kwargs):
with mock.patch('myscript.api_call',
side_effect=[self.make_sound(**kwargs),
self.make_sound(**kwargs)]):
output1 = parent_function(**kwargs)
output2 = parent_function(**kwargs)
请注意,这未经测试,但可能会给您一些想法。