有没有一种方法可以计算使用一组特定参数调用函数模拟的次数?

时间:2020-05-11 17:56:39

标签: python unit-testing automated-tests pytest

我有一个模拟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做这件事吗?

1 个答案:

答案 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)

请注意,这未经测试,但可能会给您一些想法。