238 votes

Python Mocking d'une fonction d'un module importé

Je veux comprendre comment @patch une fonction d'un module importé.

Voilà où j'en suis pour l'instant.

app/mocking.py :

from app.my_module import get_user_name

def test_method():
  return get_user_name()

if __name__ == "__main__":
  print "Starting Program..."
  test_method()

app/my_module/__init__.py :

def get_user_name():
  return "Unmocked User"

test/mock-test.py :

import unittest
from app.mocking import test_method 

def mock_get_user():
  return "Mocked This Silly"

@patch('app.my_module.get_user_name')
class MockingTestTestCase(unittest.TestCase):

  def test_mock_stubs(self, mock_method):
    mock_method.return_value = 'Mocked This Silly')
    ret = test_method()
    self.assertEqual(ret, 'Mocked This Silly')

if __name__ == '__main__':
  unittest.main()

Cela ne pas fonctionnent comme je m'y attendais. Le module "patché" renvoie simplement la valeur non simulée de get_user_name . Comment puis-je simuler les méthodes d'autres paquets que j'importe dans un espace de nom en cours de test ?

322voto

Matti John Points 2734

Lorsque vous utilisez le patch du décorateur de l unittest.mock paquet que vous êtes Parcheandoil dans l'espace de nom qui est en cours d'essai (dans ce cas app.mocking.get_user_name ), et non pas l'espace de nom à partir duquel la fonction est importée (dans ce cas-ci app.my_module.get_user_name ).

Pour faire ce que vous décrivez avec @patch essayez quelque chose comme ci-dessous :

from mock import patch
from app.mocking import test_method 

class MockingTestTestCase(unittest.TestCase):

    @patch('app.mocking.get_user_name')
    def test_mock_stubs(self, test_patch):
        test_patch.return_value = 'Mocked This Silly'
        ret = test_method()
        self.assertEqual(ret, 'Mocked This Silly')

La documentation de la bibliothèque standard comprend un outil utile section en décrivant ceci.

27voto

Tgilgul Points 709

Si la réponse de Matti John résout votre problème (et m'a aidé aussi, merci !), je vous suggère cependant de localiser le remplacement de la fonction originale 'get_user_name' par la fonction simulée. Cela vous permettra de contrôler quand la fonction est remplacée et quand elle ne l'est pas. De plus, cela vous permettra d'effectuer plusieurs remplacements dans le même test. Pour ce faire, utilisez l'instruction 'with' d'une manière assez similaire :

from mock import patch

class MockingTestTestCase(unittest.TestCase):

    def test_mock_stubs(self):
        with patch('app.mocking.get_user_name', return_value = 'Mocked This Silly'):
            ret = test_method()
            self.assertEqual(ret, 'Mocked This Silly')

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X