I am trying to test the following class using unittest and the mock library:
class Connection(object):
def __init__(self, cookie):
self.connect = None
self.session = Session()
self.session.load(cookie)
# do some stuff with self.session
self.some_info = self.session.data['the_info']
How could I test if when I create an instance of Connection, depending on the return of the Session instance, I assert if self.some_info is with the value I am expecting?
I wish to use the mock library. In its documentation I have an example of mocking chained calls (http://www.voidspace.org.uk/python/mock/examples.html#mocking-chained-calls), but it isn't very clear of how I can adapt it to my problem.
The Session.load(cookie) method sets some attributes in the Session instance. I would like to set this values fixed for my tests for every value of cookie.
Assume Connection is located in module package.module.connection
The following code should be how you would test your session:
import mock
class TestConnection(unittest.TestCase):
#mock.patch('package.module.connection.Session')
def test_some_info_on_session_is_set(self, fake_session):
fake_session.data = {'the_info': 'blahblah'}
cookie = Cookie()
connection = Connection(cookie)
self.assertEqual(connection.some_info, 'blahblah')
fake_session.load.assert_called_once_with(cookie)
Related
I've been battling with this for awhile and cannot get my head around how I patch an ldap object that I initialize inside an upstream module, in this case ldap.
I'm trying to patch the "simple_bind_s" method, but this isn't a method from ldap, rather a method accessible from an LdapObject.
import ldap
import mock
import pytest
class ActiveDirectory():
def __init__(self, ad_username, ad_password):
self.ad_username = ad_username
self.ad_password = ad_password
ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER)
self.ad_connection = ldap.initialize(self.ldap_server)
def connect(self):
self.ad_connection.simple_bind_s(self.ad_username,self.ad_password)
# patch here
def test_connect():
ad = ActiveDirectory('foo', 'bar')
ad.connect()
I'm working on unit tests for a service I made that uses confluent-kafka. The goal is to test successful function calls, exception errors, etc. The problem I'm running into is since I'm instantiating the client in the constructor of my service the tests are failing since I'm unsure how to patch a constructor. My question is how do I mock my service in order to properly test its functionality.
Example_Service.py:
from confluent_kafka.schema_registry import SchemaRegistryClient
class ExampleService:
def __init__(self, config):
self.service = SchemaRegistryClient(config)
def get_schema(self):
return self.service.get_schema()
Example_Service_tests.py
from unittest import mock
#mock.patch.object(SchemaRegistryClient, "get_schema")
def test_get_schema_success(mock_client):
schema_Id = ExampleService.get_schema()
mock_service.assert_called()
The problem is that you aren't creating an instance of ExampleService; __init__ never gets called.
You can avoid patching anything by allowing your class to accept a client maker as an argument (which can default to SchemaRegistryClient:
class ExampleService:
def __init__(self, config, *, client_factory=SchemaRegistryClient):
self.service = client_factory(config)
...
Then in your test, you can simply pass an appropriate stub as an argument:
def test_get_schema_success():
mock_client = Mock()
schema_Id = ExampleService(some_config, client_factory=mock_client)
mock_client.assert_called()
Two ways
mock entire class using #mock.patch(SchemaRegistryClient) OR
replace #mock.patch.object(SchemaRegistryClient, "get_schema") with
#mock.patch.object(SchemaRegistryClient, "__init__")
#mock.patch.object(SchemaRegistryClient, "get_schema")
I am using pytest to test a method that calls requests.post. Is there a easy way and preferably without third party libraries to do this?
class Dispatcher:
def __init__(self, url):
self.url = url
self.session = None
def dispatch(self):
return self.session.post(self.url).json()
def test_dispatch():
d = Dispatcher(url="")
d.session = # ... here, how can I mock the return value of json()?
result = d.dispatch()
So this is a pretty straightforward example. We want to set session to be a MagicMock object.
from unittest.mock import MagicMock
def test_dispatch():
expected = {"fizz": "buzz"}
mock_session = MagicMock()
mock_session.configure_mock(
**{
"post.return_value": mock_session,
"json.return_value": expected
}
)
d = Dispatcher(url="")
d.session = mock_session
result = d.dispatch()
assert result == expected
Since Mock objects return a brand new mock object when methods are called on them (without being configured), we have to configure the object as such. If we didn't configure post to return the original mock we have, then it would return a brand new mock object and our test would fail. Conversely you can configure another Mock object to be the return value of post and configure that object, but I prefer this approach.
Explanation showing the call is listed below.
self.session is our mock_session object we created
self.session.post(arg, **kwargs) returns mock_session
mock_session.json() returns the dictionary we specified
Here I am using unittest framework and Python.
def getsomevalue(name):
client = hvac.Client(url ="http://1.2.3.4:31485",token = "abcdefghijkkk")
sampledata= client.read('secret/data/somedata')
return sampledata
So pretty much what I did was create a mock hvac client class and then patch to replace the vault client instance in your code.
in other words it is something like this:
def mock_vault_read(*args, **kwargs):
class MockVault:
def read(self, **kwargs):
return {some_data}
and then for your test you can write:
#patch("hvac.Client", side_effect=mock_vault_read):
def test_read(self, mock_vault):
name = "test"
result = getsomevalue(name)
self.assertEquals(result, {some_data})
What this is doing is creating a magic mock mock_vault and replacing all instances of hvac.Client that it can find with that magic mock. The mock_vault_read is a side_effect of that magic mock, essentially saying that when you call the magic mock, call the mock_vault_read function. This can be further customized for any function need for hvac.
I'm mocking an internal library class (Server) of python that provides connection to HTTP JSON-RPC server. But when running the test the class is not mocking. The class is used calling a project class that is a wrapper for other class that effectively instantiates the Server class.
I extract here the parts of the code that give sense for what I'm talking about.
Unit test:
#patch('jsonrpc_requests.jsonrpc.Server')
def test_get_question_properties(self, mockServer):
lime_survey = Questionnaires()
# ...
Class Questionnaires:
class Questionnaires(ABCSearchEngine):
""" Wrapper class for LimeSurvey API"""
def get_question_properties(self, question_id, language):
return super(Questionnaires, self).get_question_properties(question_id, language)
Class Questionnaires calls the method get_question_properties from class ABCSearchEnginge(ABC). This class initializes the Server class to provide the connection to the external API.
Class ABCSearchEnginge:
class ABCSearchEngine(ABC):
session_key = None
server = None
def __init__(self):
self.get_session_key()
def get_session_key(self):
# HERE the self.server keep getting real Server class instead the mocked one
self.server = Server(
settings.LIMESURVEY['URL_API'] + '/index.php/admin/remotecontrol')
As the test is mocking Server class why it's not mocking? What is the missing parts?
From what i see you didnt add a return value.
Were did you put the mocked value in : #patch('jsonrpc_requests.jsonrpc.Server') ?
If you try to add a MagicMock what happend (Dont forget to add from mock import patch, MagicMock)?
#patch('jsonrpc_requests.Server', MagicMock('RETURN VALUE HERE'))
You also need to Mock the __init__ method (Where Server is this one from jsonrpc_requests import Server):
#patch.object(Server, '__init__', MagicMock(return_value=None))
I extrapolated your problem from my own understanding, maybe you need to fix some path (Mock need the exact path to do the job).