Print can be mocked in the following way:
import unittest
import builtin
class TestSomething(unittest.TestCase):
@mock.patch('builtins.print')
def test_method(self, print_):
some_other_module.print_something()
However this means that in the python debug console (pydev debugger) and in the unit test method itself print
cannot be used. This is rather inconvenient.
Is there a way to only mock the print
method in some_other_module
instead of in the testing module as well?
A way to sidestep this is to swap the use of print in the test module with some other function which just calls print
, which I can do if there turns out to be no better solution.
@michele's "final solution" has an even cleaner alternative which works in my case:
from unittest import TestCase
from unittest.mock import patch
import module_under_test
class MyTestCase(TestCase):
@patch('module_under_test.print', create=True)
def test_something(self, print_):
module_under_test.print_something()
print_.assert_called_with("print something")
Yes you can! ... But just because you are using Python 3. In Python 3 print
is a function and you can rewrite it without change the name. To understand the final solution I'll describe it step by step to have a final flexible and non intrusive solution.
The trick is add at the top of your module that you will test a line like:
print = print
And now you can patch just print
of your module. I wrote a test case where the mock_print_module.py
is:
print = print
def print_something():
print("print something")
And the test module (I'm using autospec=True
just to avoid errors like mock_print.asser_called_with
):
from unittest import TestCase
from unittest.mock import patch
import mock_print_module
class MyTestCase(TestCase):
@patch("mock_print_module.print",autospec=True)
def test_something(self,mock_print):
mock_print_module.print_something()
mock_print.assert_called_with("print something")
You can use patch
on "builtins.print"
without lose print functionality just by use side_effect
patch
's attribute:
@patch("builtins.print",autospec=True,side_effect=print)
def test_somethingelse(self,mock_print):
mock_print_module.print_something()
mock_print.assert_called_with("print something")
Now you can trace your prints call without lose the logging and pydev debugger. The drawback of that approach is that you must fight against lot of noise to check your interested the print calls. Moreover you cannot chose what modules will be patched and what not.
You cannot use both way together because if you use print=print
in your module you save builtins.print
in print
variable at the load module time. Now when you patch builtins.print
the module still use the original saved one.
If you would have a chance to use both you must wrap original print and not just record it. A way to implement it is use following instead of print=print
:
import builtins
print = lambda *args,**kwargs:builtins.print(*args,**kwargs)
Do we really need to modify the original module to have a chance to patch all print calls in it? No, we can do it without change the module to test anyway. The only thing that we need is injecting a local print
function in the module to override the builtins
's one: we can do it in the test module instead of the the module to test. My example will become:
from unittest import TestCase
from unittest.mock import patch
import mock_print_module
import builtins
mock_print_module.print = lambda *args,**kwargs:builtins.print(*args,**kwargs)
class MyTestCase(TestCase):
@patch("mock_print_module.print",autospec=True)
def test_something(self,mock_print):
mock_print_module.print_something()
mock_print.assert_called_with("print something")
@patch("builtins.print",autospec=True,side_effect=print)
def test_somethingelse(self,mock_print):
mock_print_module.print_something()
mock_print.assert_called_with("print something")
and mock_print_module.py
can be the clean original version with just:
def print_something():
print("print something")
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