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 .