web-dev-qa-db-fra.com

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

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

C'est où je suis si loin.

app/mocking.py:

from app.my_module import get_user_name

def test_method():
  return get_user_name()

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

app/mon_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 __== '__main__':
  unittest.main()

Ceci pas fonctionne comme prévu. Le module "corrigé" renvoie simplement la valeur non amortie de get_user_name. Comment puis-je simuler des méthodes à partir d'autres packages que je suis en train d'importer dans un espace de noms testé?

82
nsfyn55

Lorsque vous utilisez le décorateur patch à partir du unittest.mock le paquet que vous êtes ne corrige pas l'espace de nom depuis lequel le module est importé (dans ce cas, app.my_module.get_user_name) vous corrigez l’application dans l’espace-noms à tester app.mocking.get_user_name.

Pour faire ce qui précède avec Mock, essayez quelque chose comme ce qui suit:

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 inclut un utile section décrivant cela.

116
Matti John

Bien que la réponse de Matti John résolve votre problème (et m'aide aussi, merci!), Je suggérerais toutefois de localiser le remplacement de la fonction d'origine "get_user_name" par celle qui a été falsifiée. Cela vous permettra de contrôler quand la fonction est remplacée et quand elle ne l’est pas. En outre, cela vous permettra de faire plusieurs remplacements dans le même test. Pour ce faire, utilisez la déclaration 'with' de la même manière:

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')
7
Tgilgul