Mock Python's built in print function

前端 未结 11 1911
醉话见心
醉话见心 2020-12-06 09:10

I\'ve tried

from mock import Mock
import __builtin__

__builtin__.print = Mock()

But that raises a syntax error. I\'ve also tried patching

相关标签:
11条回答
  • 2020-12-06 09:41

    First, the module is called __builtins__ and you don't need to import it.

    Now, in Python 2 print is a keyword so you can't use it as an attribute name directly. You can use setattr/getattr to workaround it:

    getattr(__builtins__, "print")
    

    Another option is to use from __future__ import print_function which changes how Python parses the module to Python 3 syntax.

    0 讨论(0)
  • 2020-12-06 09:42

    As lcq says, print is a keyword. So, think about what it would mean if you were actually successful in patching/mocking print under Python 2.7.3. You would have code like this:

    print "Hi."
    

    turning into:

    <MagicMock id='49489360'> "Hi."
    

    MagicMock objects cannot be accessed this way, so you would get a syntax error.

    So... Yeah. You can only mock the Python3 print function or sys.stdout.

    0 讨论(0)
  • 2020-12-06 09:43

    print is a keyword in python 2.x, using it as attribute raises a SyntaxError. You can avoid that by using from __future__ import print_function in the beginning of the file.

    Note: you can't simply use setattr, because the print function you modified doesn't get invoked unless the print statement is disabled.

    Edit: you also need to from __future__ import print_function in every file you want your modified print function to be used, or it will be masked by the print statement.

    0 讨论(0)
  • 2020-12-06 09:47
    import mock
    import sys
    
    mock_stdout = mock.Mock()
    sys.stdout = mock_stdout
    print 'Hello!'
    sys.stdout = sys.__stdout__
    
    print mock_stdout.mock_calls
    [call.write('Hello!'), call.write('\n')]
    
    0 讨论(0)
  • 2020-12-06 09:48

    This Python 3 example builds upon the Python 2 answer by Krzysztof. It uses unittest.mock. It uses a reusable helper method for making the assertion.

    import io
    import unittest
    import unittest.mock
    
    from .solution import fizzbuzz
    
    
    class TestFizzBuzz(unittest.TestCase):
    
        @unittest.mock.patch('sys.stdout', new_callable=io.StringIO)
        def assert_stdout(self, n, expected_output, mock_stdout):
            fizzbuzz(n)
            self.assertEqual(mock_stdout.getvalue(), expected_output)
    
        def test_only_numbers(self):
            self.assert_stdout(2, '1\n2\n')
    
    0 讨论(0)
提交回复
热议问题