简体   繁体   中英

Using mock patch to mock an instance method

I'm trying to mock something while testing a Django app using the imaginatively named Mock testing library . I can't seem to quite get it to work, I'm trying to do this:

models.py

from somelib import FooClass

class Promotion(models.Model):
    foo = models.ForeignKey(FooClass)
    def bar(self):
       print "Do something I don't want!"


test.py

class ViewsDoSomething(TestCase):
    view = 'my_app.views.do_something'

    def test_enter_promotion(self):
        @patch.object(my_app.models.FooClass, 'bar')
        def fake_bar(self, mock_my_method):
            print "Do something I want!"
            return True

        self.client.get(reverse(view))

What am I doing wrong?

To add onto Kit's answer, specifying a 3rd argument to patch.object() allows the mocked object/method to be specified. Otherwise, a default MagicMock object is used.

    def fake_bar(self):
        print "Do something I want!"
        return True

    @patch.object(my_app.models.FooClass, 'bar', fake_bar)
    def test_enter_promotion(self):
        self.client.get(reverse(view))
        # Do something I want!

Note that, if you specify the mocking object, then the default MagicMock() is no longer passed into the patched object -- eg no longer:

def test_enter_promotion(self, mock_method):

but instead:

def test_enter_promotion(self):

http://www.voidspace.org.uk/python/mock/patch.html#patch-object

Ah I was confused on where to apply that patch decorator. Fixed:

class ViewsDoSomething(TestCase):
    view = 'my_app.views.do_something'

    @patch.object(my_app.models.FooClass, 'bar')
    def test_enter_promotion(self, mock_method):
        self.client.get(reverse(view))

If you'd like to do assert_called etc. against the mocked method, use the patch.object and wrap replacement method in a MagicMock(side_effect=) , ie:

with patch.object(class_to_mock, attribute_name, \
 MagicMock(side_effect=replacement_method)) as replacement_method_mock:

eg.:

from unittest.mock import patch, MagicMock

def fake_bar(self):
    print "Do something I want!"
    return True

def test_enter_promotion(self):
    with patch.object(my_app.models.FooClass, 'bar', MagicMock(side_effect=fake_bar)) as fake_bar_mock:
        self.client.get(reverse(view))
        # Do something I want!
        fake_bar_mock.assert_called()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM