Python undo method mock
Asked Answered
B

1

19

I am using Mock to replace method from a class with a specific return value. It works very well, maybe a little too well... I do this (see below), but in the next test class, I reuse the password class without mocking, and the mock placed in that test is still effective.

from utils import password as pass_helper

class TestPassword(unittest.TestCase):
    def setUp(self):
        self.username = "user"
        self.password = "Test_1234_pass"
        pass_helper._get_password_from_keyboard = Mock(return_value=self.password)

    def test_password(self):
        password = pass_helper._get_password_from_keyboard(self.username)
        self.assertEqual(password, self.password)

I tried undoing the mock in the TearDown method by doing something like this, but it does not work.

pass_helper._get_password_from_keyboard = pass_helper._get_password_from_keyboard

How can I restore the original functionnality of the class method?

Bisayas answered 6/8, 2013 at 13:48 Comment(0)
L
18

The problem, as it looks like you have gathered, is that the changes you make aren't restricted to the scope of the test, but instead bleed into other tests (which is of course a big problem when unit testing). Your idea of reversing the change in your teardown method is a good one, however the problem is that you are re-assigning the mock version of the method back to itself when you do this:

pass_helper._get_password_from_keyboard = pass_helper._get_password_from_keyboard

Something like this should work, where before mocking the method you assign the 'real' version of the method to a temporary variable:

def setUp(self):
    self.username = "user"
    self.password = "Test_1234_pass"
    self.real_get_password_from_keyboard = pass_helper._get_password_from_keyboard
    pass_helper._get_password_from_keyboard = Mock(return_value=self.password)

def tearDown(self):
    pass_helper._get_password_from_keyboard = self.real_get_password_from_keyboard

def test_password(self):
    password = pass_helper._get_password_from_keyboard(self.username)
    self.assertEqual(password, self.password)

Hope this helps!

Lovins answered 6/8, 2013 at 15:13 Comment(2)
after I do this, I get unbound method xxx must be called with xxx instance as the first argument (got int instead)Afterdeck
This issue got us today albeit it was with MagicMock but exactly the same "bleeding" behaviour. Pulled my hair for a few hours before discovering this post. Thanks robjohncox!Holomorphic

© 2022 - 2024 — McMap. All rights reserved.