TL;DR
How can I patch or mock "any functions that are not being called/used directly"?
Sceneario
I have a simple unit-test snippet as
# utils/functions.py
def get_user_agents():
# sends requests to a private network and pulls data
return pulled_data
# my_module/tasks.py
def create_foo():
from utils.functions import get_user_agents
value = get_user_agents()
# do something with value
return some_value
# test.py
class TestFooKlass(unittest.TestCase):
def setUp(self):
create_foo()
def test_foo(self):
...
Here in setUp() method I am calling get_user_agents() function indirectly by calling create_foo(). During this execution I have got socket.timeout exception since get_user_agents() tried to access a private network. So, how can I manipulate the return data or the entire get_user_agents function during the test?
Also, is there any way to persists this mock/patch during the whole test suite execution?
It does not matter that you call the function indirectly - important is to patch it as it is imported. In your example you import the function to be patched locally inside the tested function, so it will only be imported at function run time. In this case you have to patch the function as imported from its module (e.g. 'utils.functions.get_user_agents'):
class TestFooKlass(unittest.TestCase):
def setUp(self):
self.patcher = mock.patch('utils.functions.get_user_agents',
return_value='foo') # whatever it shall return in the test
self.patcher.start() # this returns the patched object, i case you need it
create_foo()
def tearDown(self):
self.patcher.stop()
def test_foo(self):
...
If you had imported the function instead at module level like:
from utils.functions import get_user_agents
def create_foo():
value = get_user_agents()
...
you should have patched the imported instance instead:
self.patcher = mock.patch('my_module.tasks.get_user_agents',
return_value='foo')
As for patching the module for all tests: you can start patching in setUp as shown above, and stop it in tearDown.
Related
For instance, every time a test finds
database.db.session.using_bind("reader")
I want to remove the using_bind("reader")) and just work with
database.db.session
using mocker
Tried to use it like this in conftest.py
#pytest.fixture(scope='function')
def session(mocker):
mocker.patch('store.database.db.session.using_bind', return_value=_db.db.session)
But nothing has worked so far.
Code under test:
from store import database
results = database.db.session.using_bind("reader").query(database.Order.id).join(database.Shop).filter(database.Shop.deleted == False).all(),
and I get
AttributeError: 'scoped_session' object has no attribute 'using_bind' as an error.
Let's start with an MRE where the code under test uses a fake database:
from unittest.mock import Mock, patch
class Session:
def using_bind(self, bind):
raise NotImplementedError(f"Can't bind {bind}")
def query(self):
return "success!"
database = Mock()
database.db.session = Session()
def code_under_test():
return database.db.session.using_bind("reader").query()
def test():
assert code_under_test() == "success!"
Running this test fails with:
E NotImplementedError: Can't bind reader
So we want to mock session.using_bind in code_under_test so that it returns session -- that will make our test pass.
We do that using patch, like so:
#patch("test.database.db.session.using_bind")
def test(mock_bind):
mock_bind.return_value = database.db.session
assert code_under_test() == "success!"
Note that my code is in a file called test.py, so my patch call applies to the test module -- you will need to adjust this to point to the module under test in your own code.
Note also that I need to set up my mock before calling the code under test.
I was checking this trying to assign a method call in a module-level variable with the intention of being executed only once, but not sure why before running any of my unit tests it will pass through all the global references of the module, the problem with this is that I have a third party method that I am assigning to a global variable and fails because is trying to execute the actual method in this first pass through, I see that this behaviour is the same even with a simple local method, here an example to replicate it, this is in a file called
project_name.app.py
def printing_values():
# this is corrected mocked, as I am using patch in unit test to
# mock this but only available in the context of the test but not
# globally
print('from mocked printing_values method', SSM_VALUE)
return SSM_VALUE
def get_ssm():
return "value_from_method"
# this line will execute get_ssm before any unit test,
# how mock this to always have a mock value
SSM_VALUE = get_ssm()
Here is my unit test
""" response_transformer TESTS """
import unittest
from unittest import mock
import project_name.app
class TestGlobalVariable(unittest.TestCase):
#mock.patch('project_name.app.SSM_VALUE', 'testing_value')
def test_success_response_global_variable(self):
response = project_name.app.printing_values()
assert response == "testing_value"
So I would like to mock SSM_VALUE but not executing the get_ssm method associated with it, how should I achieve this?
""" response_transformer TESTS """
import unittest from unittest import mock
import project_name.app
class TestGlobalVariable(unittest.TestCase):
#mock.patch('project_name.app.printing_values')
def test_success_response_global_variable(self, mock_printing_values):
mock_printing_values.return_value = 'testing_value'
response = project_name.app.printing_values()
assert response == "testing_value"
I am used to pytest approach for unit testing, without using classes. Today I wanted to give a try to unittest and I wanted to encapsulate my tests inside a TestCase.
Then consider this sample test class:
import unittest
import moto
import boto3
class TestMyClass(unittest.TestCase):
#classmethod
#moto.mock_ssm
def setUpClass(cls) -> None:
cls.ssm_client = boto3.client('ssm')
cls.ssm_client.put_parameter(Name='test', Value='foo', Type='String')
#moto.mock_ssm
def test_something(self):
value = self.ssm_client.get_parameter(Name='test').get('Parameter').get('Value')
self.assertEqual(value, 'foo')
Why is not the parameter placed in setUpClass visible from the test? I could imagine that by using the #moto.mock_ssm decorator there it would all have been done in the mocked context.
I can, however, place the parameter within test_something as just:
#moto.mock_ssm
def test_something(self):
self.ssm_client.put_parameter(Name='test', Value='foo', Type='String')
value = self.ssm_client.get_parameter(Name='test').get('Parameter').get('Value')
self.assertEqual(value, 'foo')
And then it (obviously) works. Why not with my first approach? I do not want to be populating the fake ssm parameter for each test that will rely on it. What is the best way of doing so here?
The reason why I am asking this is because the class I want to test requires this parameter when it is initialised.
The mock-decorators are scoped for that particular function, so data created inside that function will only be available there.
Instead, you can use the class-decorator:
import unittest
import moto
import boto3
#moto.mock_ssm
class TestMyClass(unittest.TestCase):
client = None
def setUp(self) -> None:
self.client = boto3.client('ssm')
self.client.put_parameter(Name='test', Value='foo', Type='String')
def test_something(self):
value = self.client.get_parameter(Name='test').get('Parameter').get('Value')
self.assertEqual(value, 'foo')
Note that I've switched to setUp, instead of setUpClass. Because setUpClass is a classmethod, it is executed before the decorator is applied, and it will try to execute this method against AWS itself.
I am mocking out a method of a class and want to test the instance of the class that the method was called from to test that the creation part of my function works as expected.
In my particular case do_stuff tries to write bar_instance to an Excel File and I don't want that to happen i.e.
def create_instance(*args):
return Bar(*args)
class Bar():
def __init__(self, *args):
self.args = args
def do_stuff(self):
pass
def foo(*args):
bar_instance = create_instance(*args)
bar_instance.do_stuff()
Then in a testing file
from unittest import TestCase
from unittest.mock import patch
from path.to.file import foo
class TestFoo(TestCase):
#patch('path.to.file.Bar.do_stuff')
def test_foo(self, mock_do_stuff):
test_args = [1]
_ = foo(*test_args)
# Test here the instance of `Bar` that `mock_do_stuff` was called from
# Something like
actual_args = list(bar_instance.args)
self.assertEqual(test_args, actual_args)
I put a break in the test function after foo(*test_args) is run but can't see any way from the mocked method of accessing the instance of Bar it was called from and am a bit stuck. I don't want to mock out Bar further up the code as I want to make sure the correct instance of Bar is being created.
In your code example, there are three things that might need testing: function create_instance, class Bar and function foo. I understand your test code such that you want to ensure that function foo calls do_stuff on the instance returned by create_instance.
Since the original create_instance function has control over the created instance, a solution of your problem is to mock create_instance such that your test gains control of the object that is handed over to foo:
import unittest
from unittest import TestCase
from unittest.mock import patch, MagicMock
from SO_60624698 import foo
class TestFoo(TestCase):
#patch('SO_60624698.create_instance')
def test_foo_calls_do_stuff_on_proper_instance (
self, create_instance_mock ):
# Setup
Bar_mock = MagicMock()
create_instance_mock.return_value = Bar_mock
# Exercise
foo(1, 2, 3) # args are irrelevant
# Verify
Bar_mock.do_stuff.assert_called()
if __name__ == '__main__':
unittest.main()
In addition, you might also want to test if foo passes the arguments correctly to create_instance. This could be implemented as a separate test:
...
#patch('SO_60624698.create_instance')
def test_foo_passes_arguments_to_create_instance (
self, create_instance_mock ):
# Setup
create_instance_mock.return_value = MagicMock()
# Exercise
foo(1, 22, 333)
# Verify
create_instance_mock.assert_called_with(1, 22, 333)
And, certainly, to complete the whole test of the object generation, you could test create_instance directly, by calling it and checking on the returned instance of Bar if it has used its arguments correctly for the construction of the Bar instance.
As patch returns an instance of Mock (or actually MagicMock, but it inherits the relevant methods from its base - Mock), you have the assert_called_with method available, which should do the trick.
Note that this method is sensitive to args/kwargs - you have to assert the exact same call.
Another note: it might be a better practice to use patch.object instead of patch here
I want to test this class using python unittest framework and also mockito.
class ISightRequestEngine(object):
def __init__(self, pInputString=None):
self.__params = (pInputString)
def openHTTPConnection(self):
pass
def __closeHTTPConnection(self):
pass
def testFunc(self):
print 'test function called'
def startEngine(self):
self.__params.parseinputString()
self.openHTTPConnection()
self.testFunc()
def processRequest(self, header = None):
pass
I wanted to test that function startEngine() calls testFunc().
Similar to what we do in our mocked class,
obj = mock(ISightRequestEngine)
obj.startEngine()
try:
verify(obj).startEngine()
except VerificationError:
Unfortunately this only verifies whether the startEngine function is called or not, but it does not give the actual function call and I cannot verify that whether the call to testFunc() has been made or not.
Is there any way to test this scenario?
I am new to testing world and framework.
In your example you are testing your mock.
You create a mock of ISightRequestingEngine
You call startEngine() method of that mock
You verify that the mocked object was called
What you want to do is:
Mock out testFunc()
Call startEngine()
Verify that testFunc() was called
I'm not familiar with mockito, but what from what I can make up from the documentation, I think you have to do something like the following:
from mockito import mock, verify
# Setup ---------------------------------------------
my_mock = mock(ISightRequestingEngine)
system_under_test = ISightRequestingEngine()
system_under_test.testFunc = my_mock.testfunc # Mock out only testFunc()
# Exercise ------------------------------------------
system_under_test.startEngine()
# Verify --------------------------------------------
verify(my_mock).testFunc()
Having similar such issue, where I am bit lost in writing the test case
class UserCompanyRateLimitValidation:
def __init__(self, user_public_key):
self.adapter = UserAdapter(user_public_key)
container = self.adapter.get_user_company_rate_limit()
super(UserCompanyRateLimitValidation, self).__init__(container,\
UserCompanyRateLimitValidation.TYPE)
I have to test this function. I have written test case something like this. I have tried to mock the UserAdapter class but I am not able to do so completely.
def test_case_1():
self.user_public_key = 'TEST_USER_PUBLIC_KEY_XXXXXX1234567890XXXXX'
UserAdapter_mock = mock(UserAdapter)
when(UserAdapter_mock).get_user_company_rate_limit().\
thenReturn(self.get_container_object())
self.test_obj = UserCompanyRateLimitValidation(self.user_public_key)
Here if you see I have mocked get_user_company_rate_limit() call from the testable function, container = self.adapter.get_user_company_rate_limit()
but I am still not able to figure out the way in which I can mock this call,
self.adapter = UserAdapter(user_public_key)