Je ne suis pas bien. C'est un problème.
Lorsque j'ai utilisé le simulacre que j'ai écrit dans Article précédent, j'étais accro à environ 2 points.
Prenons le cas du test d'un module qui utilise une bibliothèque externe comme suit. (Dans l'exemple suivant, la bibliothèque http requêtes est utilisée comme bibliothèque externe. Certains points de la description suivante dépendent des requêtes. C'est le contenu qui a été fait.) Pour tester ce module seul, vous pouvez vous moquer des classes de la bibliothèque externe.
python:Module à tester(A.target.Que ce soit py)
from requests import Session
#Utilisez la classe Session quelque part
s = Session()
Ici, si vous écrivez comme suit, vous ne pouvez pas bien vous moquer de la bibliothèque externe.
Maquette de bibliothèque externe(Erreur)
import A
from mock import patch
# A.Se moquer de la classe Session utilisée dans la cible(Je vais)
with patch('requests.Session'):
#tester
Le point est de savoir comment importer la bibliothèque externe dans le module sous test.
Si from requests import Session
est spécifié, la classe Session sera placée sous l'espace du module où l'importation a été exécutée.
Si le module testé est ʻA.target.py, ce sera ʻA.target.Session
.
Le module testé utilise la classe Session (ʻA.target.Session`) importée sous lui, donc vous devez vous en moquer.
Maquette de bibliothèque externe(correct)
import A
from mock import patch
# A.Se moquer de la classe Session importée dans la cible
with patch('A.target.Session'):
#tester
D'un autre côté, que faire si vous dites «demandes d'importation»?
Module à tester(Lorsque vous n'utilisez pas de)
import requests
#Utilisez la classe Session quelque part
s = requests.Session()
Cette fois, au lieu d'importer la classe Session sous mon contrôle, je spécifie requests.Session
et le package de la bibliothèque externe.
Par conséquent, la cible fictive est également «requests.Session» au lieu de «A.target.Session».
Maquette de bibliothèque externe(Lorsque vous n'utilisez pas de)
import A
from mock import patch
#Se moquer de la classe Session dans le package de requêtes
with patch('requests.Session'):
#tester
Avec patch
, l'attribut cible spécifié (méthode, etc.) est également automatiquement simulé. Dans ce cas, la classe Mock appelée MagicMock est utilisée par défaut.
Exemple de moquerie de l'attribut de la cible spécifiée
>>> import requests
>>> from mock import patch
# requests.La méthode de publication de la classe Session est simulée
>>> with patch('requests.Session'):
s = requests.Session()
print(s.post)
...
<MagicMock name='Session().post' id='4401343792'>
Considérez le cas où la simulation de réponse est définie comme la valeur de retour de la méthode post de la classe requests.Session qui est automatiquement simulée ci-dessus. Puisque la réponse de la méthode de publication a une propriété "texte", il est supposé que la même propriété (simulée) est définie dans la réponse fictive à créer.
Utilisez PropertyMock pour simuler des propriétés. Même si vous utilisez MagicMock, vous ne pouvez pas spécifier la valeur de retour de la propriété (= valeur de retour du getter).
Utilisez MagicMock pour les propriétés(Échec)
>>> import requests
>>> from mock import patch, MagicMock
>>> with patch('requests.Session'):
s = requests.Session()
response = MagicMock()
# 'text'Propriétés simulées avec MagicMock(Essayez de)
text = MagicMock()
text.return_value = 'property'
response.text = text
s.post.return_value = response
print(s.post().text)
...
# text.return_La valeur spécifiée pour value n'est pas renvoyée
<MagicMock name='Session().post().text' id='4506288536'>
Cependant, le simple remplacement de MagicMock par PropertyMock ne change pas le résultat.
Utilisez PropertyMock pour les propriétés(Échec)
>>> import requests
>>> from mock import patch, MagicMock, PropertyMock
>>> with patch('requests.Session'):
s = requests.Session()
response = MagicMock()
#Utilisez PropertyMock au lieu de MagicMock
text = PropertyMock()
text.return_value = 'property'
response.text = text
s.post.return_value = response
print(s.post().text)
...
#Ne fonctionne toujours pas...
<PropertyMock name='Session().post().text' id='4506377240'>
Il s'agit d'un problème qui se produit lorsque vous essayez de définir un PropertyMock pour une instance fictive (la réponse simulée dans l'exemple ci-dessus). Dans ce cas, vous devez définir PropertyMock sur l'objet type et non sur l'objet simulé lui-même.
Utilisez PropertyMock pour les propriétés(Succès)
>>> import requests
>>> from mock import patch, MagicMock, PropertyMock
>>> with patch('requests.Session'):
s = requests.Session()
response = MagicMock()
text = PropertyMock()
text.return_value = 'property'
#Si vous définissez PropertyMock sur une autre maquette, définissez-la sur ce type d'objet, et non sur l'objet maquette lui-même.
type(response).text = text
s.post.return_value = response
print(s.post().text)
...
property
Les deux étaient correctement écrits dans le document ...
http://www.voidspace.org.uk/python/mock/patch.html#where-to-patch http://www.voidspace.org.uk/python/mock/mock.html?highlight=propertymock#mock.PropertyMock
Lisons le document correctement.
Recommended Posts