Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AttributeError: None does not have the attribute 'print'

So I am practicing some unit test and I am trying to check for an output that is within a For Loop. Here is my run code

def main():

  for i in range(100):
    print("Argh!")

Pretty basic, now here is my test code.

import unittest
from unittest import mock  # possibly "from unittest import mock" depending on version.
from RunFile import main

class TestMain(unittest.TestCase):
    def test_main(self):
        with mock.patch.object(main(), 'print') as mock_print:
            main()
        expected_calls = [mock.call('Argh!') for _ in range(100)]
        mock_print.assert_has_calls(expected_calls)

if __name__ == '__main__':
    unittest.main()

Here is the error message I get back. I'm not to sure how to resolve this. UPDATED: Here is the full trace back

======================================================================
ERROR: test_main (__main__.TestMain)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:/Users/jsalce/Documents/Testsuites/IfStatements/Testsuite.py", line 9, in test_main
    with mock.patch.object(RunFile, 'print') as mock_print:
  File "C:\Python33\lib\unittest\mock.py", line 1148, in __enter__
    original, local = self.get_original()
  File "C:\Python33\lib\unittest\mock.py", line 1122, in get_original
    "%s does not have the attribute %r" % (target, name)
AttributeError: <module 'RunFile' from      'C:\\Users\\jsalce\\Documents\\Testsuites\\IfStatements\\RunFile.py'> does not have the attribute 'print'

----------------------------------------------------------------------
Ran 1 test in 0.001s

FAILED (errors=1)

Thank you all in advance!

like image 320
salce Avatar asked Oct 20 '22 01:10

salce


1 Answers

Generally speaking, for mock.patch.object, you want to patch something that you have an easy handle on -- e.g. a module or a class. Usually, you need to patch something that is one level above what you want to replace. For example if you want to patch the foo function in module bar, then you need mock.patch.object(bar, 'foo').

In your case, technically, print is a builtin, but you can patch it on the module where you're using it. This will add a RunFile.print "method" (which is actually a mock) that you can test assertions against. Apparently, since print doesn't actually exist on the module, we need to add create=True to tell mock to create RunFile.print since it doesn't already exist. With that in mind, I'd re-write the unittest as:

import RunFile

class TestMain(unittest.TestCase):
    def test_main(self):
        with mock.patch.object(RunFile, 'print', create=True) as mock_print:
            RunFile.main()
        expected_calls = [mock.call('Argh!') for _ in range(100)]
        mock_print.assert_has_calls(expected_calls)

if __name__ == '__main__':
    unittest.main()
like image 194
mgilson Avatar answered Oct 22 '22 17:10

mgilson