Is it possible to mock a module that's imported inside of a function?
for instance
def my_func(input):
import something_else
something_else.do_something(input)
I have an import inside of the function because of a circular dependency. Based on my googling I think I am SOL, but was wondering if anyone knew of way to make this possible.
I just want to verify that do_something gets called.
You can use the same technique that's described in this answer. In short you can patch sys.modules dict. So your test can be:
from unittest.mock import patch, MagicMock
...
def test_call_do_something(self):
m = MagicMock()
with patch.dict("sys.modules", something_else=m):
input_mock = MagicMock()
my_func(input_mock)
m.do_something.assert_called_with(input_mock)
You can rewrite it by patch decorator, but m should be a static instance.
Related
The most common way to patch something in a module seems to be to use something like
from unittest.mock import patch
from mypackage.my_module.my_submodule import function_to_test
#patch('mypackage.my_module.my_submodule.fits.open')
def test_something(self, mock_fits_open)
# ...
mock_fits_open.return_value = some_return_value
function_to_test()
# ...
However, with the value passed to the patch decorator being a string, I don't get lots of the nice benefits from IDE. I can't use parts of the string to jump to definitions. I don't get autocomplete (and an implicit spelling check). Nor full refactoring capabilities. And so on.
Using patch.object I can get much closer to what I'm looking for.
from unittest.mock import patch
import mypackage.my_module.my_submodule
from mypackage.my_module.my_submodule import function_to_test
#patch.object(mypackage.my_module.my_submodule.fits, 'open')
def test_something(self, mock_fits_open)
# ...
mock_fits_open.return_value = some_return_value
function_to_test()
# ...
However, this still requires the final part of the name of the referenced object is just a string. Is there a (nice) way to patch an object purely on the reference to that object? That is, I would like to be able to do something like
from unittest.mock import patch
import mypackage.my_module.my_submodule
from mypackage.my_module.my_submodule import function_to_test
#patch.reference(mypackage.my_module.my_submodule.fits.open)
def test_something(self, mock_fits_open)
# ...
mock_fits_open.return_value = some_return_value
function_to_test()
# ...
Patching works by replacing in the namespace where the name is looked up.
The underlying logic of mock.patch is essentially working with a context-managed name shadowing. You could do the same thing manually with:
save original value associated with name (if any)
try overwriting the name
execute the code under test
finally resetting name back to the original value
Therefore, you fundamentally need to patch on a name, there is no patching a reference directly.
You can use the __name__ attribute of the function object:
from unittest.mock import patch
import my_module
#patch.object(my_module, my_module.my_fun.__name__)
def test_something(self, mocked_fun)
# ...
See also: Name of a Python function in a stack trace
I have a function that has a decorator. The decorator accepts arguments and the value of the argument is derived from another function call.
example.py
from cachetools import cached
from cachetools import TTLCache
from other import get_value
#cached(cache=TTLCache(maxsize=1, ttl=get_value('cache_ttl')))
def my_func():
return 'result'
other.py
def get_value(key):
data = {
'cache_ttl': 10,
}
# Let's assume here we launch a shuttle to the space too.
return data[key]
I'd like to mock the call to get_value(). I'm using the following in my test:
example_test.py
import mock
import pytest
from example import my_func
#pytest.fixture
def mock_get_value():
with mock.patch(
"example.get_value",
autospec=True,
) as _mock:
yield _mock
def test_my_func(mock_get_value):
assert my_func() == 'result'
Here I'm injecting mock_get_value to test_my_func. However, since my decorator is called on the first import, get_value() gets called immediately. Any idea if there's a way to mock the call to get_value() before module is imported right away using pytest?
Move the from example import my_func inside your with in your test function. Also patch it where it's really coming from, other.get_value. That may be all it takes.
Python caches modules in sys.modules, so module-level code (like function definitions) only runs on the first import from anywhere. If this isn't the first time, you can force a re-import using either importlib.reload() or by deleting the appropriate key in sys.modules and importing again.
Beware that re-importing a module may have side effects, and you may also want to re-import the module again after running the test to avoid interfering with other tests. If another module was using objects defined in the re-imported module, these don't just disappear, and may not be updated the way it expects. For example, re-importing a module may create a second instance of what was supposed to be a singleton.
One more robust approach would be save the original imported module object somewhere else, delete from sys.modules, re-import with the patched version for the duration of the test, and then put back the original import into sys.modules after the test. You could do this with an import inside of a patch.dict() context on sys.modules.
import mock
import sys
import pytest
#pytest.fixture
def mock_get_value():
with mock.patch(
"other.get_value",
autospec=True,
) as _mock, mock.patch.dict("sys.modules"):
sys.modules.pop("example", None)
yield _mock
def test_my_func(mock_get_value):
from example import my_func
assert my_func() == 'result'
Another possibility is to call the decorator yourself in the test, on the original function. If the decorator used functools.wraps()/functools.update_wrapper(), then original function should be available as a __wrapped__ attribute. This may not be available depending on how the decorator was implemented.
I am trying to use unittests.mock to mock a void method call of an object.
My package is like below
common
baseupgradehandler.py
baseupgradehandler.py
class BaseUpgradeHandler(object):
def __init__(self, upgrade_config, upgrade_state, system_config, pre_step, main_step, post_step):
...
# Method call to be supressed
def start(self, service_manifest, upgrade_bundle):
# type: (service_version_pb2.ServiceManifest, str) -> ()
...
In my test code I am trying to mock the call to start() like below as explained in the documentation.
from workflow.upgradeworkflow import UpgradeWorkflow
from common.serviceregistry import ServiceRegistry
# The above imports are at the start of the test file
...
with patch('common.baseupgradehandler.BaseUpgradeHandler') as handler_mock: # type: Mock
handler_mock.return_value.start.return_value = ''
wf = UpgradeWorkflow(ServiceRegistry(self.service_bundle, config, sys_config, state),
config,
state,
sys_config)
BaseUpgradeHandler object is returned by get_upgrade_handler() method of ServiceRegistry. When I am executing the above code in test I am seeing the BaseUpgradeHandler.start() is still getting called.
Can someone let me know how can I mock the call to a start() so that the method is not called?
EDIT
If I change my patching code like below it is working as expected and BaseUpgradeHandler is getting mocked and start is not getting called.
with patch('common.baseupgradehandler.BaseUpgradeHandler') as handler_mock: # type: Mock
handler_mock.return_value.start.return_value = ''
with patch('common.serviceregistry.ServiceRegistry') as serviceregistry_mock: # type: Mock
serviceregistry_mock.return_value.get_upgrade_handler.return_value = handler_mock
wf = UpgradeWorkflow(ServiceRegistry(self.service_bundle, config, sys_config, state), config, state, sys_config)
wf.start()
Can someone explain me why do I have to patch ServiceRegistry as well?
The code you provided is not enough to see the part that causes the issue. We'd need to see the module serviceregistry to be sure but I'd take an educated guess:
You have a file a.py (aka baseupgradehandler) like this:
class A:
def method(self):
print("It's real!")
And a file b.py (aka serviceregistry) like this:
from a import A
class B:
def get_A(self):
return A()
In your test files you do this:
import unittest
from unittest.mock import patch
from b import B
from a import A
GAME OVER!
The B module right now has already got its reference to the original A class. When, afterwards, you patch('a.A') only the reference in the a module is changed, but patch has no way to know that B has its own reference to the original A.
You can fix this in three ways:
patch the method: this will modify the existing class so all references to that class will be automatically patched
patch b.A too:
with patch('a.A') as h_a, patch('b.A') as h_b:
h_a.return_value.method.return_value = ''
h_b.return_value.method.return_value = ''
Avoid importing the modules before patching (probably not feasible or a good idea):
import unittest
from unittest.mock import patch
class MyTest(unittest.TestCase):
def test_one(self):
with patch('a.A') as h:
h.return_value.method.return_value = ''
from b import B
B().get_A().method()
I have been using unittest.mocks for a while, and I have been re-inventing the wheel sometimes. I decided to make mockito part of my project and now things look way better. Any kind of mock verification is really simple, if you can, I definitively encourage you to make mockito part of your libraries. This library has a good documentation and so far it has been easier than unittest.mock IMHO.
During a test phase, I would like to modify a part of my source code. For instance, I don't need to plot, so the code responsible for plotting can be commented. Is there a proper tool in unittest module to do so?
Another question is regarding the decorator #patch. Is there a way I can put them into source code in runtime during testing?
Try working with mock,
As it sounds it mocks your code and can be manipulated thru the test.
You may mock an method returned val or an object instance etc etc.
https://www.toptal.com/python/an-introduction-to-mocking-in-python
As Ohad the Lad already said, mocks are at your help.
There are several ways how to mock a function, but in general, you will decorate your test-functions - not the function to mock!
In your case the code could look as follows:
# your_file.py
from ... import ... as plt #depends on the class you use
class MyPlotter(object):
def draw_calling_method(self):
....
plt.draw()
...
return something
# test.py
import mock
from unittest import TestCase
from your_file import MyPlotter
from ... import ... as plt # same import as in the your_file.py
class TestMyPlotter(TestCase):
#mock.patch.object(plt, 'draw')
def test_draw_calling_method_returns_something(self, draw):
plotter = MyPlotter()
plotter_return = plotter.draw_calling_method()
self.assertEqual(plotter_return, something)
This will replace all calls to the plt.draw() with MagicMocks and hinder the draw-execution. If all of your test-methods need to mock the draw-call, the mock decorator could also be applied to the class instead. You only have to make sure then, that all your test-methods accept the mock as second argument (as the test_draw_calling_mehtod_returns_something does). Further you could mock any return values the draw() function may have by setting draw.return_value = ... in the test-method. Attention: This has to happen prior to the call of the function which calls the mock, otherwise the return-values will not be applied.
For more information on mocking refer to the docs python-docs. They are quite comprehensive.
One last thing; As Jonathon Reinhart already mentioned, if you feel it difficult to write your tests it may be good to refactor your code before. This will not only make it more testable, but more readable as well!
I'm noticing that the class methods are being mocked out properly, but the function is bypassing the mock and running the actual function.
from module1 import myClass
from module2 import my_function
import unittest
from mock import patch
class TestStuff(unittest.TestCase):
#patch('module2.my_function')
#patch('module1.myClass.my_method')
def test_my_function(self, mock_method, mock_function):
test_obj = myClass()
test_obj.my_method()
assert mock_method.called
my_function()
assert mock_function.called
if I print out my_function() and type(my_function) it will not show the mock, but the real function. Does it matter that I'm importing a class then mocking a method, but I'm importing the function directly?
I think I found the issue:
When I'm testing a function, and there's something I want to mock, I should not import it. Importing it causes it to get used, even if I've put the patch decorator.
I think this was general confusion about how mocking/testing works. What I wanted to do was to test a function without actually querying the database. Instead of mocking out the whole function, I could take the line that actually hits the db - query.all() - and make it it's own function, then mock that out.
from module1 import myClass
from module2 import my_function
import unittest
from mock import patch
class TestStuff(unittest.TestCase):
#patch('module2.db_query')
#patch('module1.myClass.my_method')
def test_my_function(self, mock_method, mock_db_query):
test_obj = myClass()
test_obj.my_method()
assert mock_method.called
my_function() # my_function calls db_query(), now mocked out
assert mock_db_query.called
If I had wanted to actually mock out the all of my_function, I could have just not imported it. At least that's how I'm understanding this at the moment.
I ran into a similar issue. Turns out I needed to give it the FULL path to my_function:
#patch('home.myuser.myprojects.mymodule.myfunc')