10

I am attempting to build a test for a Python application using mock and the @patch decorator.

Given the following directory structure:

  |-- mypackage
  |   |-- mymodule
  |   |   |-- __init__.py
  |   |   \-- somefile.py
  |   \-- myothermodule
  |       |-- tests
  |       |   |-- __init__.py
  |       |   \-- test_func_to_test.py
  |       \-- __init__.py
  \-- __init__.py

Where the content of the files are:


#mypackage/mymodule/somefile.py

def some_function():
    return 'A'

#mypackage/myothermodule/__init__.py

from mypackage.mymodule.somefile import some_function

def func_to_test():
    return some_function()

#mypackage/myothermodule/tests/test_func_to_test.py

from unittest import TestCase
from mock import patch

class TestFunc_to_test(TestCase):
    def test_func_to_test(self):
        from mypackage.myothermodule import func_to_test
        self.assertEqual('A', func_to_test())

    @patch('mypackage.mymodule.somefile.some_function')
    def test_func_to_test_mocked(self, some_mock_function):
        from mypackage.myothermodule import func_to_test
        some_mock_function.return_value = 'B'
        self.assertEqual('B', func_to_test())

The problem I have is that, while the first test passes (test_func_to_test), the second test (test_func_to_test_mocked) does not (due to an AssertionError).

I have been able to mock function from "built-in" modules (like requests.get, for example) using the same approach, however I can't seem to get the @patch working when trying to patch a function from one of my modules...

Any help would be appreciated :)

lucidity14
  • 233
  • 3
  • 7

1 Answers1

31

mypackage.myothermodule has already been imported, so the name some_function is already bound within that module. You need to mock the usage of that name within the module it is being called from:

@patch('mypackage.myothermodule.some_function')

You could alternatively reload mypackage.myothermodule:

import mypackage.myothermodule
reload(mypackage.myothermodule)
ecatmur
  • 152,476
  • 27
  • 293
  • 366
  • 1
    This is the holy-grail answer that I'd been searching for over the past 3-6 years. Google's and SE's algorithms need to boost this. – Dave Liu Aug 26 '21 at 22:38
  • 2
    "You need to mock the usage of that name within the module it is being called from" That's the key. – Ebram Shehata Dec 13 '21 at 15:06