I'm new to testing and testing in python. I have a python class that looks like this :
File name : my_hive.py
from pyhive import hive
class Hive:
def __init__(self, hive_ip):
self.cursor = hive.connect(hive_ip).cursor()
def execute(self, command):
self.cursor.execute(command)
I want to mock these functions : pyhive.hive.connect, pyhive.Connection.cursor(used by my class as hive.connect(hive_ip).cursor()) and pyhive.Cursor.execute (used by my class as self.cursor.execute(command) in execute method).
I'm able to mock function call hive.connect and also I have been able to assert that it has been called with hive_ip given by me as follows.
import unittest
import mock
from my_hive import Hive
class TestHive(unittest.TestCase):
#mock.patch('pyhive.hive.connect')
def test_workflow(self, mock_connect):
hive_ip = "localhost"
processor = Hive(hive_ip)
mock_connect.assert_called_with(hive_ip)
But how do I make sure that subsequent function calls like .cursor() and self.cursor.execute() have also been called? hive.connect(hive_ip) returns an instance of pyhive.hive.Connection, which has method called cursor
I have tried to add mocks like this :
import unittest
import mock
from hive_schema_processor import HiveSchemaProcessor
class TestHive(unittest.TestCase):
#mock.patch('pyhive.hive.connect')
#mock.patch('pyhive.hive.Connection.cursor')
def test_workflow(self, mock_connect, mock_cursor):
hive_ip = "localhost"
processor = Hive(hive_ip)
mock_connect.assert_called_with(hive_ip)
mock_cursor.assert_called()
But the tests are failed with complain :
AssertionError: expected call not found.
Expected: cursor('localhost')
Actual: not called.
Your problem is that you have already mocked connect, so the subsequent calls on the result of connect will be made on the mock, not on the real object.
To check that call, you have to make the check on the returned mock object instead:
class TestHive(unittest.TestCase):
#mock.patch('pyhive.hive.connect')
def test_workflow(self, mock_connect):
hive_ip = "localhost"
processor = Hive(hive_ip)
mock_connect.assert_called_with(hive_ip)
mock_cursor = mock_connect.return_value.cursor
mock_cursor.assert_called()
Each call on a mock produces another mock object.
mock_connect.return_value gives you the mock that is returned by calling mock_connect, and mock_connect.return_value.cursor contains another mock that will actually be called.
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"
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.
I wrote a wrapper class around the Cassandra driver module and I'm in the process of writing unit tests for it. I can unit test that a particular method of a class was called (e.g. connect). However, asserting that this was called is not enough. I want to make sure that the params passed to my wrapper method (i.e. open_session) when I instantiate the class are the ones I expect.
How can I unittest the instantiation of a class before any method is called upon it?
My wrapper class:
from cassandra.cluster import Cluster
class CassandraWrapper(object):
def __init__(self, hosts, port):
self.session = self.open_session(hosts, port)
def open_session(self, hosts, port):
cluster = Cluster(contact_points=hosts, port=port)
return cluster.connect()
My unit tests:
from cassandra_wrapper import CassandraWrapper
from unittest.mock import patch
import unittest
class TestCassandraWrapper(unittest.TestCase):
#patch('cassandra.cluster.Cluster.connect')
def test_open_session(self, connect_mock):
cw = CassandraWrapper(['localhost'], 9042)
connect_mock.assert_called_once()
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)