Python se moquant d'une fonction à partir d'un module importé

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

C'est là que je suis jusqu'à présent.

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 Fonctionne comme je m'y attendais. Le module "patché" renvoie simplement la valeur non verrouillée de get_user_name. Comment puis-je me moquer des méthodes d'autres paquets que j'importe dans un espace de noms en cours de test?

59
demandé sur bennylope 2013-04-21 21:48:07

2 réponses

Lorsque vous utilisez le décorateur patch du paquet unittest.mock, Vous ne corrigez pas l'espace de noms à partir duquel le module est importé (dans ce cas app.my_module.get_user_name) vous le corrigez dans l'espace de noms en cours de test 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 standard de la bibliothèque comprend une section utile décrivant ceci.

81
répondu Matti John 2017-10-27 11:20:55

Alors que la réponse de Matti John résout votre problème (et m'a aidé aussi, merci!), Je suggère cependant de localiser le remplacement de la fonction originale 'get_user_name' par la fonction moqué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 de faire plusieurs remplacements dans le même test. Pour ce faire, utilisez la déclaration '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')
5
répondu Tgilgul 2015-02-20 13:43:59