15

I have recently noticed that if I mock out a method using mock.patch it doesn't list the instance object passed to the mocked method in the call_args field. Is this by design? Code/output below may better explain what I mean:

#!/usr/bin/env python2

from mock import patch

class Dog(object):
    def bark(self):
        print("Woof woof!")

Dog().bark()

def new_method(*args):
    print("args = %s" % str(args))

Dog.bark = new_method

Dog().bark()

with patch.object(Dog, "bark"):
    d = Dog()
    d.bark()
    print("d.bark was called: %s" % str(d.bark.called))
    print("d.bark was called with args/kwargs: %s" % str(d.bark.call_args))

Output is:

Woof woof!
args = (<__main__.Dog object at 0x7f42c2dbc3d0>,)

# Mocking bit
d.bark was called: True
d.bark was called with args/kwargs: ((), {})

You can see that the instance object is passed to new_method when it replaces bark. But you cannot see it in the call_args of the mocked out method. Isn't this strange? I am using version 1.01 of the python mock library.

spenibus
  • 4,339
  • 11
  • 26
  • 35
NaKhaaaaan
  • 153
  • 1
  • 4

1 Answers1

26

By

with patch.object(Dog, "bark"):

You are patching the static instance of Dog.bark method because you are patching Dog class and not a Dog object.

Now the mock method will be called as a static method and not as object method: that means the self attribute will not passed.

If you want create a patch with the same signature of original method you can use autospec=True attribute: in this case the mock method will be an object method instead of a static method.

>>> from mock import patch
>>> with patch.object(Dog, "bark", autospec=True):
...     d = Dog()
...     d.bark()
...     print("d.bark was called with args/kwargs: %s" % str(d.bark.call_args))
... 
<MagicMock name='bark()' id='139848306278672'>
d.bark was called with args/kwargs: call(<Dog object at 0x7f30f89ef390>)
Michele d'Amico
  • 22,111
  • 8
  • 69
  • 76