unittest python3 mock example python python-mock

python3 - python unittest



AplicaciĆ³n de parches simulados de/import en Python (3)

Estoy intentando que mock.patch funcione en el siguiente fragmento de código de muestra:

from mock import patch from collections import defaultdict with patch(''collections.defaultdict''): d = defaultdict() print ''d:'', d

Esto produce lo siguiente:

d: defaultdict(None, {})

Lo que significa que el defaultdict no fue parcheado.

Si sustituyo la declaración desde / importación con una instrucción de importación directa, funciona:

from mock import patch import collections with patch(''collections.defaultdict''): d = collections.defaultdict() print ''d:'', d

La salida es:

d: <MagicMock name=''defaultdict()'' id=''139953944084176''>

¿Hay alguna forma de parchear una llamada usando desde / importar?

Gracias


Los nombres pueden ser muy confusos en este caso. Siempre queremos burlarnos de una definición de clase en un espacio de nombres. El espacio de nombres es el módulo en el que tiene lugar la importación. La definición de clase es el nombre usado en ese espacio de nombres.

Tomemos un ejemplo concreto:

  • El módulo myproj.utilities contiene la clase Actor.
  • myproj.application importa esto from myproj.utilities import Actor
  • Mi prueba debería ejecutar my.proj.application y burlarse de nuestro Actor

myproj.utilities.py

class Actor: def __init__(name): self.name = name

myproj.application.py

from myproj.utilities import Actor class App: def __init__(name): self.actor = Actor(name)

código de prueba

from mock import patch from myproj.application import App test: # format: patch(''<namespace>.<Class>'') # the namespace in which we with to mock # the class definition we wish to mock with patch(''myproj.application.Actor''): app = App(''Someone'') print( type(app.actor) ) # expect a MagicMock

Probé varios otros enfoques y este funciona bien para mí. No he probado el código anterior, sino que lo generalicé de mi caso específico. Por lo tanto, podría ser un poco apagado.


Si está parcheando algo en el mismo módulo, puede usar __main__ :

from mock import patch from collections import defaultdict with patch(''__main__.defaultdict''): d = defaultdict() print ''d:'', d

Sin embargo, si se burla de algo por un módulo importado, querrá usar el nombre de ese módulo para que la referencia (o nombre) correcta esté parcheada:

# foo.py from collections import defaultdict def bar(): return defaultdict() # foo_test.py from mock import patch from foo import bar with patch(''foo.defaultdict''): print bar()

El punto aquí es que el parche quiere la ruta completa a lo que está parchando. Esto solo parece un poco extraño al parchear algo en el módulo actual, ya que la gente no suele usar __main__ (o deben referirse al módulo actual, para el caso).


patch funciona parcheando nombres . No puede lograr nada parcheando el nombre collections.defaultdict si está usando el nombre defaultdict (en el espacio de nombres local) para acceder al objeto. Consulte la documentación en http://www.voidspace.org.uk/python/mock/patch.html#id1 .