I\'ve tried
from mock import Mock
import __builtin__
__builtin__.print = Mock()
But that raises a syntax error. I\'ve also tried patching
My version.
In the tested program(ex: pp.py
):
from __future__ import print_function
def my_func():
print('hello')
In the test program:
def test_print(self):
from pp import my_func
from mock import call
with mock.patch('__builtin__.print') as mock_print:
my_func()
mock_print.assert_has_calls(
[
call('hello')
]
)
I know that there is already an accepted answer but there is simpler solution for that problem - mocking the print in python 2.x. Answer is in the mock library tutorial: http://www.voidspace.org.uk/python/mock/patch.html and it is:
>>> from StringIO import StringIO
>>> def foo():
... print 'Something'
...
>>> @patch('sys.stdout', new_callable=StringIO)
... def test(mock_stdout):
... foo()
... assert mock_stdout.getvalue() == 'Something\n'
...
>>> test()
Of course you can use also following assertion:
self.assertEqual("Something\n", mock_stdout.getvalue())
I have checked this solution in my unittests and it is working as expected. Hope this helps somebody. Cheers!
If you want to stick with the print
statement from 2.x as opposed to the print()
function from 2.x, you could mock your sys.stdout
instead.
Write a dummy "file", perhaps in about this way:
class Writable(object):
"""Class which has the capability to replace stdout."""
newwrite = None
def __init__(self, oldstdout, newwrite=None):
self.oldstdout = oldstdout
if newwrite is not None:
self.newwrite = newwrite
def write(self, data):
self.newwrite(self.oldstdout, data)
@classmethod
def subclass(cls, writefunc):
newcls = type('', (cls,),
dict(write=lambda self, data: writefunc(self.oldstdout, data)
return newcls
This class expects to be combined with a writing function which gets the printed data. This writing function is supposed to take 2 arguments: the first one with the "old stdout" to be used for printing at the end, and a further one for the data.
Let's take
def mywrite(sink, data):
sink.write(data.encode("hex"))
for that.
Now you can do
import sys
sys.stdout = Writable(sys.stdout, mywrite)
or you can do
@Writable.subclass
def mywritable(sink, data)
sink.write(data.encode("hex"))
sys.stdout = mywritable(sys.stdout)
The 2nd version is a bit trickier: it creates a subclass of the Writable
with the help of a decorator function which turns the given function into a method of the new class created instead and put into the name where the given function comes from.
After that, you have a new class which can be instantiated with the "old stdout" as argument and can replace sys.stdout
after that.
This is a v3 version of @KC's answer.
I didn't want to mock print because I specifically wanted to see the output as a whole, not check out individual calls so StringIO makes more sense to me.
from io import StringIO
from unittest.mock import patch
def foo():
print ('Something')
def test():
with patch('sys.stdout', new_callable=StringIO) as buffer:
foo()
fake_stdout = buffer.getvalue()
#print() is back!
print(f"fake_stdout:{fake_stdout}")
assert fake_stdout == 'Something\n'
test()
from unittest.mock import patch
def greet():
print("Hello World")
@patch('builtins.print')
def test_greet(mock_print):
greet()
mock_print.assert_called_with("Hello World!")
This is a much simpler Python 3 solution -- it's easier to use unittest.mock
directly on the builtin print
function, rather than fiddling around with sys.stdout
:
from unittest.mock import patch, call
@patch('builtins.print')
def test_print(mocked_print):
print('foo')
print()
assert mocked_print.mock_calls == [call('foo'), call()]