5

I am trying to test the module:

package/module.py

DATA_PATH = os.path.join(os.path.dirname(__file__), "data")
class SomeClass:
    def __init__(self):
        self.filename = os.path.join(DATA_PATH, "ABC.txt")

in tests/module_test.py I am trying to do

from package import module
@patch("package.module.DATA_PATH", "data_path_here") # doesn't work
class TestSomeClass(unittest.TestCase):
    def setUp(self):
        module.DATA_PATH = "data_path_here" # doesn't work
        self.obj= SomeClass()

    @patch("package.module.DATA_PATH", "data_path_here") # doesn't work either
    def test_constructor(self):
        self.assertEqual(r"data_path_here\ABC.txt", self.obj.filename)

but the DATA_PATH is still not mocked out. I think that I tried all the possible options to mock it out but it still returns original path instead of "data_path_here"

What am I doing wrong?

EDIT: It is not a duplicate of Modifying global variables in Python unittest framework Because that solution does not work

Alicja Głowacka
  • 401
  • 5
  • 11
  • Possible duplicate of [Modifying global variables in Python unittest framework](https://stackoverflow.com/questions/6268278/modifying-global-variables-in-python-unittest-framework) – quamrana May 01 '18 at 13:44
  • it is not a duplicate because that solution does not work – Alicja Głowacka May 01 '18 at 14:16
  • You might want to confirm a forward vs back slash issue on the test ... is the path really separated with a \ or a / ?? That would make the "assignment" approach in the setup work. – F1Rumors May 01 '18 at 14:52

2 Answers2

5

You don't need patching since you are using a global variable from another module:

#module.py

DATA_PATH = 1

def getData():
    return DATA_PATH


#tests.py
from package import module

print(module.DATA_PATH, module.getData())
module.DATA_PATH = 2
print(module.DATA_PATH, module.getData())

Output:

1 1
2 2
quamrana
  • 37,849
  • 12
  • 53
  • 71
  • 1
    this is better and cleaner without mocking. – Gang May 01 '18 at 23:53
  • amazing, thank you. I had to import the module and change the value on the module as you've done. e.g. `import module` and `module.var = `. `from module import var` and then setting `var = ` did not make a persistent change. – Nick Brady May 13 '20 at 20:26
  • When you use `from module import var` and then `var = something` you are only using your own module's `var` and you don't affect `module.var`. Mandatory link to [Ned Batchelder](https://nedbatchelder.com/text/names.html) – quamrana May 13 '20 at 20:30
  • This should be the correct answer, works for my case! – TDAK Mar 04 '21 at 08:30
1

For me, using mock/patch is a painful exercise. On the other hand, it was trivial to accomplish by setting (and restoring) the global for the tests:

import mock_module

class TestSomeClass(unittest2.TestCase):
    def setUp(self):
        self._original = mock_module.DATA_PATH
        mock_module.DATA_PATH = 'data_path_here'

    def tearDown(self):
        mock_module.DATA_PATH = self._original

    def test_constructor(self):
        obj = mock_module.SomeClass()
        self.assertEqual(r"data_path_here\ABC.txt", obj.filename)

Note that for my os path join, the separator is \ but your usage may differ.

Ran 1 test in 0.005s

OK

F1Rumors
  • 920
  • 9
  • 13