web-dev-qa-db-fra.com

Est-il possible de réinitialiser une méthode simulée à son état d'origine? - Python Mock - mock 1.0b1

J'ai la classe simplifiée suivante dont je me moque:

class myClass(object):
    @staticmethod
    def A():
        #...

    def check(self):
        #code...
        value = self.A()
        #more code...

Dans mon premier test, je me moque uniquement de la méthode A

from Django.test import TestCase
from mock import MagicMock
import myClass

class FirstTest(TestCase):

def setUp(self):
    myClass.A = MagicMock(return_value = 'CPU')

def test(self):
    #some tests 
    myClassObj = myClass()
    myClassObj.check()

Alors que dans mon deuxième test, je me moque de toute la méthode de vérification:

from Django.test import TestCase
from mock import MagicMock
import myClass

class SecondTest(TestCase):

def setUp(self):
    myClass.check = MagicMock(return_value = someObject)

def test(self):
    #some tests 
    myClassObj = myClass()
    myClassObj.check()

Maintenant, mes assertions de mon premier test échouent parce qu'au lieu d'appeler check() et de se moquer de A() à l'intérieur de check(), il appelle la check() complètement moquée de mon deuxième test.

Existe-t-il un moyen d'effacer et de définir la méthode comme "normale" après le test? J'ai déjà essayé myClass.check.reset_mock(), mais il ne semble rien faire. Déplacer l'ordre de mes tests ne fait rien non plus.

J'utilise mock 1.0b1 pour python de http://pypi.python.org/pypi/mock/

32
SaiyanGirl

Vous pouvez ranger la fonction sur vous-même et la remettre lorsque vous avez terminé.

import unittest

from mock import MagicMock
from MyClass import MyClass

class FirstTest(unittest.TestCase):

    def setUp(self):
        self.A = MyClass.A
        MyClass.A = MagicMock(name='mocked A', return_value='CPU')


    def tearDown(self):
        MyClass.A = self.A

    def test_mocked_static_method(self):
        print 'First Test'
        print MyClass.check
        print MyClass.A


class SecondTest(unittest.TestCase):

    def setUp(self):
        MyClass.check = MagicMock(name='mocked check', return_value=object)

    def test_check_mocked_check_method(self):
        print 'Second Test'
        print MyClass.check
        print MyClass.A


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

L'exécution de ce fichier donne la sortie suivante:

First Test
<unbound method MyClass.check> 
<MagicMock name='mocked A' id='141382732'>
Second Test
<MagicMock name='mocked check' id='141382860'>
<unbound method MyClass.A>

Je me suis retrouvé à utiliser le patch décorateur beaucoup plus que setUp et tearDown maintenant. Dans ce cas, vous pourriez faire

from mock import patch

@patch('MyClass.A')
def test_mocked_static_method(self, mocked_A)
    mocked_A.return_value = 'CPU'
    # This mock will expire when the test method is finished
13
aychedee

Vous pouvez utiliser mock.patch en tant que décorateur ou gestionnaire de contexte:

from mock import patch, MagicMock

@patch('myClass.A', MagicMock(return_value='CPU'))
def test(self):
    pass

ou:

def test(self):
    with patch('myClass.A', MagicMock(return_value='CPU')):
        pass

Si vous ne fournissez pas d'objet fantaisie à patch, il fournira une maquette auto-spécifiée que vous pouvez modifier:

@patch('myClass.A')
def test(self, mock_A):
    mock_A.return_value = 'CPU'
    pass

ou:

def test(self):
    with patch('myClass.A') as mock_A:
        mock_A.return_value = 'CPU'
        pass

Dans tous les cas, la valeur d'origine sera restaurée lorsque la fonction de test décorée ou le gestionnaire de contexte se terminera.

36
ecatmur