Reputation: 8488
I'm having some trouble mocking a function. Said function is imported and used in run_parsers.py
and I'm getting
ImportError: 'No module named run_parsers'
When I'm attempting to mock.patch
run_parsers.py
.
Here's my test code in test_run_parsers.py
from .. import run_parsers # Used in all my other tests.
def test_node_data_parser_throws_exception(self):
def parser():
return NotImplementedError()
with mock.patch("run_parsers.get_node_paths") as node_paths:
node_paths.return_value = "node_1"
run_parsers.get_node_data(parser, "/a/path")
Here's my repository structure
control_scripts
├── __init__.py
├── README.md
├── run_all_parsers.py
├── run_parsers.py
└── tests
├── __init__.py
├── test_run_parsers.py
According to this tutorial I'm supposed to mock where the function is imported. This is why I'm attempting to mock the calling module rather than the module that defines get_node_paths
Upvotes: 6
Views: 10852
Reputation: 147
For more complicated project structure (or if you want to make te mock parts shorter), I come up with a tricky solution, because I needed a seperation between the Logic and the UI.
My structure looks something like this:
├───sourceroot
│ ├───python_pkg
│ │ ├───__init__
│ │ └───subpkg
│ │ ├───__init__
│ │ ├───logic
│ │ │ ├───lpkg1
│ │ │ │ ├───__init__
│ │ │ │ ├───file1.py
│ │ │ │ └───file2.py
│ │ │ ├───lpkg2
│ │ │ │ ├───__init__
│ │ │ │ ├───file3.py
│ │ │ │ └───file4.py
│ │ │ ├───__init__
│ │ │ └───file.py
│ │ └───ui
│ │ ├───uipkg3
│ │ │ ├───__init__
│ │ │ ├───file_ui1.py
│ │ │ └───file_ui2.py
│ │ ├───uipkg4
│ │ │ ├───__init__
│ │ │ ├───file_ui3.py
│ │ │ └───file_ui4.py
│ │ ├───__init__
│ │ └───file_ui.py
│ └───packages
│ └───some_3rd_party_packages
├───srcfiles_from_3rd_parties
└───tests
└───unit_tests_py
├───__init__
└───test.py
I had to reference on the file.py and file1.py from test.py.
To see the sourceroot from the test.py-file I write the following into the sourceroot/tests/unit_test_py/__init__
import sys
import os
sys.path.append(os.path.realpath(os.path.join(os.path.dirname(__file__), '..', '..')))
After the Initialisation and adding the sourceroot to the paths (where Python will look up) the test.py
class is ready to Edit:
Before:
import mock
from sourceroot.python_pkg.subpkg.logic import file
from sourceroot.python_pkg.subpkg.logic.lpkg1.file1 import SomeClassFromFile1 as SCF1
class Test_test1(object):
def test_first(self, mocker):
mocker.patch('sourceroot.python_pkg.subpkg.logic.lpkg1.file1.some_function_which_SCF1_calls')
mocker.patch('sourceroot.python_pkg.subpkg.logic.file.SomeClassInFile.some_function_which_SomeClassInFile_calls')
SCF1.some_function_in_SCF1()
expected_information = True
assert SCF1.is_something() == expected_information
After:
import mock
from sourceroot.python_pkg.subpkg.logic import file
from sourceroot.python_pkg.subpkg.logic.lpkg1.file1 import SomeClassFromFile1 as SCF1
class Test_test1(object):
def test_first(self, mocker):
mocker.patch.object(SCF1, 'some_function_which_SCF1_calls')
mocker.patch.object(file.SomeClassInFile, 'some_function_which_SomeClassInFile_calls')
SCF1.some_function_in_SCF1()
expected_information = True
assert SCF1.is_something() == expected_information
Upvotes: 4
Reputation: 1033
I'm not sure if this duplicates your setup exactly, but here is a simple test case that worked for me.
The directory setup is:
c:\work
\control
__init__.py
scripts.py
\tests
__inti__.py
mytests.py
and c:\work is on sys.path
In the module scripts.py:
def identity(x):
return x
def do_identity(x):
return identity(x)
In mytests.py:
import unittest
from unittest.mock import patch
from control import scripts
class MyTest(unittest.TestCase):
def test_patch(self):
with patch('control.scripts.identity') as mymock:
mymock.return_value = 99
self.assertEqual(scripts.do_identity(1), 99)
def test_no_patch(self):
self.assertEqual(scripts.do_identity(1), 1)
if __name__ == "__main__":
unittest.main()
So what I am trying to do here is to mock the function 'identity' which is called by the function 'do_identity'. Both functions are in the 'scripts' module. This test runs with no errors or failures.
And I can run this from any directory as:
c:\any_directory> python c:\work\control\tests\mytests.py
Upvotes: 6