Le module A
comprend import B
à son sommet. Cependant , dans des conditions de test , je voudrais se moquer B
de A
(faux A.B
) et de ne pas tout à fait d'importer B
.
En fait, B
n'est pas installé exprès dans l'environnement de test.
A
est l'unité sous test. Je dois importer A
avec toutes ses fonctionnalités. B
est le module dont je dois me moquer. Mais comment puis-je me moquer de l' B
intérieur A
et arrêter A
d'importer le réel B
, si la première chose à A
faire est l'importation B
?
(La raison pour laquelle B n'est pas installé est que j'utilise pypy pour des tests rapides et malheureusement B n'est pas encore compatible avec pypy.)
Comment cela pourrait-il être fait?
la source
Mock
certains attributs magiques (__%s__
) comme__name__
.sys.modules['B'] = None
mais cela ne semble pas fonctionner.mock
, puis appelermock.Mock()
L'intégré
__import__
peut être simulé avec la bibliothèque 'mock' pour plus de contrôle:Dites
A
ressemble à:A.a()
retoursb_mock.func()
qui peuvent être moqués également.Remarque pour Python 3: comme indiqué dans le journal des modifications de la version 3.0 ,
__builtin__
est maintenant nommébuiltins
:Le code de cette réponse fonctionne bien si vous remplacez
__builtin__
parbuiltins
pour Python 3.la source
import_mock
être appelé pour leimport A
, mais pas pour tout ce qu'il importe.ImportError: No module named '__builtin__'
__builtin__
__builtin__
parbuiltins
pour python3 ( docs.python.org/3/whatsnew/3.0.html?highlight=__builtin__ )Facile, simulez simplement la bibliothèque dans sys.modules avant qu'elle ne soit importée:
et puis, tant que
A
ne repose pas sur des types spécifiques de données renvoyées par les objets de B:devrait juste fonctionner.
Vous pouvez également vous moquer
import A.B
:Cela fonctionne même si vous avez des sous-modules, mais vous voudrez vous moquer de chaque module. Dites que vous avez ceci:
Pour simuler, faites simplement ce qui suit avant que le module qui contient ce qui précède ne soit importé:
(Mon expérience: j'avais une dépendance qui fonctionne sur une plate-forme, Windows, mais qui ne fonctionnait pas sous Linux, où nous exécutons nos tests quotidiens. J'ai donc dû me moquer de la dépendance pour nos tests. Heureusement, c'était une boîte noire, donc Je n'ai pas eu besoin de mettre en place beaucoup d'interaction.)
Effets secondaires moqueurs
Addendum: En fait, j'avais besoin de simuler un effet secondaire qui prenait du temps. J'avais donc besoin de la méthode d'un objet pour dormir une seconde. Cela fonctionnerait comme ceci:
Et puis le code prend un certain temps à s'exécuter, tout comme la vraie méthode.
la source
Je me rends compte que je suis un peu en retard à la fête ici, mais voici une façon un peu insensée d'automatiser cela avec la
mock
bibliothèque:(voici un exemple d'utilisation)
La raison pour laquelle cela est si ridiculement compliqué est lorsqu'une importation se produit, python le fait essentiellement (prenez par exemple
from herp.derp import foo
)sys.modules['herp']
Existe- t- il? Sinon, importez-le. Si toujours pasImportError
sys.modules['herp.derp']
Existe- t- il? Sinon, importez-le. Si toujours pasImportError
foo
desys.modules['herp.derp']
. AutreImportError
foo = sys.modules['herp.derp'].foo
Il y a quelques inconvénients à cette solution piratée ensemble: si quelque chose d'autre repose sur d'autres éléments dans le chemin du module, ce genre de problème. De plus, cela ne fonctionne que pour les éléments importés en ligne, tels que
ou
la source
La réponse d'Aaron Hall fonctionne pour moi. Je veux juste mentionner une chose importante,
si en
A.py
toifrom B.C.D import E
alors dans
test.py
vous devez vous moquer de chaque module le long du chemin, sinon vous obtenezImportError
la source
J'ai trouvé un bon moyen de me moquer des importations en Python. C'est la solution Zaadi d' Eric trouvée ici que je viens d'utiliser dans mon application Django .
J'ai une classe
SeatInterface
qui est l'interface avec laSeat
classe de modèle. Donc, dans monseat_interface
module, j'ai une telle importation:Je voulais créer des tests isolés pour la
SeatInterface
classe avec uneSeat
classe simulée commeFakeSeat
. Le problème était - comment exécuter les tests hors ligne, là où l'application Django est en panne. J'ai eu une erreur ci-dessous:La solution était:
Et puis le test fonctionne comme par magie OK :)
la source
Si vous faites un,
import ModuleB
vous appelez vraiment la méthode intégrée__import__
comme suit :Vous pouvez écraser cette méthode en important le
__builtin__
module et créer un wrapper autour de la__builtin__.__import__
méthode. Ou vous pouvez jouer avec leNullImporter
crochet duimp
module. Attrapez l'exception et simulez votre module / classe dans leexcept
bloc-.Pointeur vers les documents pertinents:
docs.python.org:
__import__
Accéder aux composants internes d'importation avec le module imp
J'espère que ça aide. Soyez vivement conseillé d'entrer dans les périmètres les plus obscurs de la programmation python et que a) une solide compréhension de ce que vous voulez vraiment réaliser et b) une compréhension approfondie des implications est importante.
la source