Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

using self in python @patch decorator

I'm trying to use python's mock.patch to implement unit tests with nose.

class A:

    def setUp(self):
        self.b = 8 #contrived example

    @patch.object('module.class', 'function', lambda x: self.b)
    def testOne(self):
        # do test #

Here, patch complains that it doesnt know self (which is correct). What is best way to get this kind of functionality in a clean fashion?

I know I can use a global variable, or that I can mock it within the test (but that involves me cleaning up the objects at the end of the test).

like image 676
Raghuram Onti Srinivasan Avatar asked Nov 17 '14 18:11

Raghuram Onti Srinivasan


People also ask

Can you mock a decorator Python?

Mock the Decorator before the import of your function/module. The decorators and functions are defined at the time the module is loaded. If you do not mock before import, it will disregard the mock.

What does @patch do in Python?

patch() uses this parameter to pass the mocked object into your test. From there, you can modify the mock or make assertions as necessary. Technical Detail: patch() returns an instance of MagicMock , which is a Mock subclass. MagicMock is useful because it implements most magic methods for you, such as .

What is the difference between mock and MagicMock?

So what is the difference between them? MagicMock is a subclass of Mock . It contains all magic methods pre-created and ready to use (e.g. __str__ , __len__ , etc.). Therefore, you should use MagicMock when you need magic methods, and Mock if you don't need them.


1 Answers

You cannot use self on method decorator because you are in the class definition and the object doesn't exist. If you really want to access to self and not just use some static values you can consider follow approach: totest is a module in my python path and fn is the method that I would patch, moreover I'm using a fixed return_value instead a function for a more readable example

class MyTestCase(unittest.TestCase):
    def setUp(self):
        self.b = 8 #contrived example

    def testOne(self):
        with patch('totest.fn', return_value=self.b) as m:
            self.assertEqual(self.b, m())
            self.assertTrue(m.called)

    @patch("totest.fn")
    def testTwo(self,m):
        m.return_value = self.b
        self.assertEqual(self.b, m())
        self.assertTrue(m.called)

In testOne() I use patch as a context and I will have the full access to self. In testTwo() (that is my standard way) I set up my mock m at the start of the test and then use it.

Finally I used patch() instead of patch.object() because I don't really understand why you need patch.object() but you can change it as you like.

like image 147
Michele d'Amico Avatar answered Sep 20 '22 00:09

Michele d'Amico