Pregunta Burlarse de la función de Python basada en argumentos de entrada


Hemos estado usando Burlarse de para Python por un tiempo.

Ahora, tenemos una situación en la que queremos simular una función

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

Normalmente, la manera de burlarse de esto sería (suponiendo que foo sea parte de un objeto)

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

Incluso, si llamo a foo () un par de veces, puedo usar

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

Ahora, estoy frente a una situación en la que quiero devolver un valor fijo cuando el parámetro de entrada tiene un valor particular. Entonces, si digamos "my_param" es igual a "algo", entonces quiero devolver "my_cool_mock"

Esto parece estar disponible en mockito para pitón

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

He estado buscando cómo lograr lo mismo con Mock sin éxito?

¿Algunas ideas?


74
2018-04-23 05:59


origen


Respuestas:


Si side_effect es una función, luego cualquiera que sea la función que devuelve es   lo que llama al simulacro de retorno. los side_effect la función se llama con   los mismos argumentos que el simulacro. Esto le permite variar el retorno   valor de la llamada de forma dinámica, en función de la entrada:

>>> 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


100
2018-04-23 06:05



Como se indica en Objeto Python Mock con método llamado varias veces

Una solución es escribir mi propio 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

Eso hace el truco


14
2018-04-23 06:19



El efecto secundario toma una función (que también puede ser una función lambda), por lo que para casos simples puede usar:

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

6
2017-08-30 05:19



Solo para mostrar otra forma de hacerlo:

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

0
2017-12-08 21:08



Sé que es una pregunta bastante antigua, podría ayudar como una mejora con 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

-1
2017-07-02 08:04