Mocking builtins like print
is a little tricky. First, you need to know that they are stored in a special __builtins__
module:
>>> __builtins__.print("hello world")
hello world
So, you need to patch that __builtins__
module. I first tried these:
@patch("__builtins__.print", dec_print)
#and
@patch("__builtin__.print", dec_print)
But these both gave an ImportError
.
Next, I tried mock.patch
instead of just mock
, which lets you specify the object you want to patch (instead of using the string to import the object):
@patch.object(__builtins__, "print", dec_print)
This works, but then since you're calling print
inside of dec_print
, you get a RuntimeError: maximum recursion depth exceeded
error.
So, to fix that you can replace print
with sys.stdout.write
. Here is the final working code for mocking print
:
import sys
from mock import patch
def dec_print(msg):
sys.stdout.write("+++ {}\n".format(msg))
@patch.object(__builtins__, "print", dec_print)
def fun():
print("Hello")
if __name__ == "__main__":
fun()
Output:
$ python x.py
+++ Hello
Edit: in response to the new information you posted (it printed the message twice, once with the mock and once without):
You're seeing it printed twice because you put fun()
at the top level of the module, so it runs when @patch
imports tstmock
, then it runs again normally. You should wrap this call in an if __name__ == '__main__':
block (explained here).
...original code...
if __name__ == "__main__":
fun()