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.
In the given statement the real function kit. getResource() is called which leads to an NPE since function calls on resources are not mocked.
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.
The library also provides a function, called patch() , which replaces the real objects in your code with Mock instances. You can use patch() as either a decorator or a context manager, giving you control over the scope in which the object will be mocked.
In pytest , mocking can replace the return value of a function within a function. This is useful for testing the desired function and replacing the return value of a nested function within that desired function we are testing.
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>)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With