Search code examples
pythonunit-testingmockingreturnpatch

Python - unittest, mock, patch, input


so i've got a problem with my code. File 1:

class Abc(object):
...
def function1(self):
 #do something
def function2(self):
 x = input()
 return x+1

and now i'm trying to test function 2 so i wrote a test for it and i don't know what i am doing wrong:

from unittest.mock import patch
import unittest
from file1 import *

class TestBackend(unittest.TestCase):

    def test_mode_first(self):
        self.assertEqual(Abc().funcion1(), 30)

    @patch('funcion2.input', create=True)
    def test_mode_second(self, mocked_input):
        mocked_input.side_effect = ["QWE"]
        result = Abc().funcion2()
        self.assertEqual(result, 10)

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

i get ModuleNotFoundError: No module named 'function2' so what i am doing wrong in here?

thanks for your help :)


Solution

  • You get ModuleNotFoundError because funcion2 is not a module. patch doc is clear about this:

    target should be a string in the form 'package.module.ClassName'. The target is imported and the specified object replaced with the new object, so the target must be importable from the environment you are calling patch() from. The target is imported when the decorated function is executed, not at decoration time.

    This works for me when executed with python3 -m unittest discover from the directory the files are in.

    BTW you have a couple of typos in your example, e.g. Abc().funcion2(), note the missing t in funcion2.

    Also, try not to use from … import *: https://docs.quantifiedcode.com/python-anti-patterns/maintainability/from_module_import_all_used.html#using-wildcard-imports-from-import

    # file1.py
    class Abc(object):
        def function1(self):
            return 30
    
        def function2(self):
            x = input()
            return x + "1"
    


    # test_file1.py
    import unittest
    from unittest.mock import patch
    from file1 import Abc
    
    
    class TestBackend(unittest.TestCase):
        def test_mode_first(self):
            self.assertEqual(Abc().function1(), 30)
    
        @patch('builtins.input')
        def test_mode_second(self, mocked_input):
            mocked_input.return_value = "QWE"
    
            result = Abc().function2()
            self.assertEqual(result, "QWE1")