Насмешливая функция python на основе входных аргументов


мы использовали Mock для python на некоторое время.

теперь у нас есть ситуация, в которой мы хотим издеваться над функцией

def foo(self, my_param):
    #do something here, assign something to my_result
    return my_result

обычно, способ издеваться над этим был бы (предполагая, что foo является частью объекта)

self.foo = MagicMock(return_value="mocked!")

даже, если я позвоню foo () пару раз я могу использовать

self.foo = MagicMock(side_effect=["mocked once", "mocked twice!"])

теперь я столкнулся с ситуацией, в которой я хочу вернуть фиксированное значение, когда входной параметр имеет определенное значение. Так что если скажем "my_param" равно "что-то", то я хочу вернуть "my_cool_mock"

это, кажется, доступно на mockito для python

when(dummy).foo("something").thenReturn("my_cool_mock")

Я искал о том, как достичь того же с Mock без успеха?

какие идеи?

5 84

5 ответов:

если side_effect является функцией, то все, что возвращает эта функция что зовет к мнимому возвращению. Элемент side_effect функция вызывается с те же аргументы, что и у макета. Это позволяет варьировать возврат значение вызова динамически, на основе входных данных:

>>> def side_effect(value):
...     return value + 1
...
>>> m = MagicMock(side_effect=side_effect)
>>> m(1)
2
>>> m(2)
3
>>> m.mock_calls
[call(1), call(2)]

http://www.voidspace.org.uk/python/mock/mock.html#calling

Как указано в Python макет объекта с методом вызывается несколько раз

решение состоит в том, чтобы написать свой собственный side_effect

def my_side_effect(*args, **kwargs):
    if args[0] == 42:
        return "Called with 42"
    elif args[0] == 43:
        return "Called with 43"
    elif kwarg['foo'] == 7:
        return "Foo is seven"

mockobj.mockmethod.side_effect = my_side_effect

это делает трюк

побочный эффект принимает функцию (которая также может быть функция Lambda), поэтому для простых случаев вы можете использовать:

m = MagicMock(side_effect=(lambda x: x+1))

просто чтобы показать другой способ сделать это:

def mock_isdir(path):
    return path in ['/var/log', '/var/log/apache2', '/var/log/tomcat']

with mock.patch('os.path.isdir') as os_path_isdir:
    os_path_isdir.side_effect = mock_isdir

Я знаю, что это довольно старый вопрос, может помочь в качестве улучшения с помощью python lamdba

self.some_service.foo.side_effect = lambda *args:"Called with 42" \
            if args[0] == 42 \
            else "Called with 42" if args[0] == 43 \
            else "Called with 43" if args[0] == 43 \
            else "Called with 45" if args[0] == 45 \
            else "Called with 49" if args[0] == 49 else None