Se moquant d'une variable globale
J'ai essayé de mettre en œuvre de tests unitaires pour un module. Un exemple de module nommé alphabet.py est comme suit:
import database
def length_letters():
return len(letters)
def contains_letter(letter):
return True if letter in letters else False
letters = database.get('letters') # returns a list of letters
J'aimerais simuler la réponse à partir d'une base de données avec des valeurs de mon choix, mais le code ci-dessous ne semble pas fonctionner.
import unittests
import alphabet
from unittest.mock import patch
class TestAlphabet(unittest.TestCase):
@patch('alphabet.letters')
def setUp(self, mock_letters):
mock_letters.return_value = ['a', 'b', 'c']
def test_length_letters(self):
self.assertEqual(3, alphabet.length_letters())
def test_contains_letter(self):
self.assertTrue(alphabet.contains_letter('a'))
J'ai vu de nombreux exemples où des "patch" est appliqué à des méthodes et des classes, mais pas à des variables. Je préfère ne pas le patch de la méthode base de données.obtenir parce que je peut l'utiliser à nouveau avec des paramètres différents, plus tard, j'aurais besoin d'une réponse différente.
Ce que je fais mal?
OriginalL'auteur Funkatic | 2016-07-12
Vous devez vous connecter pour publier un commentaire.
Vous n'avez pas besoin d'utiliser la maquette. Il suffit d'importer le module et de modifier la valeur du global au sein de
setUp()
:Vous pouvez définir la valeur de
alphabet.letters
à ce qu'il était dans letearDown
fonction.Aussi, depuis
setUp
est étendue à l'ensemble de la classe de test, vous pouvez l'utiliser uniquement une valeur pourletters
. Sera la réponse ci-dessous vous permet de faire plusieurs objets fantaisie pour les différents cas de test, et ils nettoient eux-mêmes jusqu'à la fin donc il n'y a pas de risque d'accident de test de la pollution.OriginalL'auteur John Gordon
Essayez ceci:
Vous avez besoin d'appliquer de la maquette alors que les tests sont en cours d'exécution, et pas seulement dans
setUp()
. Nous pouvons créer la fantaisie danssetUp()
, et de l'appliquer plus tard avec unwith ...
Gestionnaire de Contexte.Pas de problème, je serais heureux de vous aider!
À l'aide de
return_value
entraînera des lettres à un callable MagicMock. Mais nous ne sommes pas à l'appel de lettres comme une fonction, et nous n'avons pas besoin de toutes les propriétés de MagicMock, nous voulons juste de remplacer la valeur. Donc, au lieu de cela, nous devrions passer directement la valeur:mock.patch.object(alphabet, 'letters', ['a', 'b', 'c'])
Le grand truc, très utile motif.
Comment cela fonctionne, si vous avez besoin de se moquer de plusieurs valeurs?
OriginalL'auteur Will
Variables peut être corrigé comme suit:
Par exemple:
OriginalL'auteur Valera Maniuk
J'ai rencontré un problème lorsque j'essayais de fantaisie sur les variables qui ont été utilisées en dehors de toute fonction ou de la classe, ce qui est problématique, car ils sont utilisés du moment où vous essayez de se moquer de la classe, avant de vous moquer des valeurs.
J'ai fini par utiliser une variable d'environnement. Si la variable d'environnement existe, utilisez cette valeur, sinon utilisez l'application par défaut. De cette façon, je pourrais définir la variable d'environnement valeur dans mes tests.
Dans mon test, j'ai eu ce code avant de la classe a été importé
Dans ma classe:
Par défaut mon
config.LOG_PATH
est/var/log/<my app name>
, mais maintenant, quand le test est en cours d'exécution, le chemin du fichier journal est définie sur le répertoire courant. De cette façon, vous n'avez pas besoin d'un accès root pour exécuter les tests.OriginalL'auteur Ruth Grace Wong