Mock the object call on function - python

I'm trying to mock the object, But it's not happening can anyone help me
payment_gateway
----payment.py
class Razz:
def __init__(self) -> None:
self.base_url = "https://api.example.com/v1"
self.api_key = os.environ["API_KEY"]
self.api_secret = os.environ["SECRET"]
self.kh_account_number = os.environ["ACCOUNT_NUMBER"]
def create_contact(self):
res = request.post(usrl=f"{base_url}/contact", data=payload, auth(self.api_key,self.api_secret)
return "id"
And am importing this class on another fille i.e event_bank_deails.py
from payment_gateway.payment import Razz, PaymentGatewayErrors
PAYMENT_GATEWAY= Razz()
def update_bank_detials(request: Request) -> Response:
contact_id = PAYMENT_GATEWAY.create_contact(body, event_id) # Creating contact
fund_id = PAYMENT_GATEWAY.create_account(contact_id, body) # Creating fund account on razorpayX
return resposes
TestCases file
#patch("event_bank_details.event_bank_details.Razz")
#pytest.mark.parametrize("input, expected_op", UPDATE_EVENT_BANK_DETAILS_INPUT)
def test_update_event_bank_details(mock_email, mock_object, input, expected_op):
from event_bank_details.event_bank_details import update_bank_detials
# mock_object.return_value.create_contact.return_value = None
# mock_object.return_value.create_account.create_account = None
response = update_bank_detials(input)
response.prepare()
response_dict = response.get()
assert response_dict["statusCode"] == expected_op
And then am writing test cases for the update_bank_details function It's throwing an error invalid API_KEYandAPI_SECREATEHow can I mock theRazzclassinit()` call on update_bank_details function???

Related

Python notify main code when variable change in another .py file

I can't wrap my head around how to accomplish the following scenario:
On my main.py and request.py i have a reference to a config.py witch contains some configuration variables.
In this sample an offline variable that are either True or False.
What I would like to do is:
If eg. in my request.py I set the config.offline = True, then I would like to do somethin on my main.py.
But main.py also references the request.py so I cannot call any functions from request.py..
Any ideas to how I can do this?
I have over 1000 lines of code, so I cannot show every thing, but i have tried to show the most important:
main.py:
import config as cfg
import request as req
def doStuffWhenOfflineVarChanges(newState):
print(newState)
config.py:
offline = True
request.py:
import config as cfg
def logEntrance(barCode, noOfGuests, dt=datetime.now()):
date = dt.strftime("%Y-%m-%d")
time = dt.strftime("%H:%M:%S")
headers = {'Content-type': 'application/json', 'Authorization': cfg.auth}
url = 'https://xxxxx.xxxxxxxx.xxx/' + cfg.customerId + '/api.ashx'
params = {"inputtype": "logentrances"}
pl = [{"Barcode": barCode , "PoeID": cfg.poeId, "UserID": cfg.userId, "EntranceDate": date, "EntranceTime": time, "NoOfGuests": str(noOfGuests), "OfflineMode": cfg.offline}]
#print(url)
print(pl)
try:
r = requests.post(url, json=pl, params=params, headers=headers)
print(r.status_code)
except:
cfg.offline = True
return r
You need a call back function to handle the change in your onfig.py file!
# config.py
offline = False
def doStuffWhenOfflineVarChanges(newState):
print(newState)
# request.py
import config as cfg
class OfflineState:
def __init__(self, callback):
self._callback = callback
self._offline = cfg.offline
#property
def offline(self):
return self._offline
#offline.setter
def offline(self, value):
self._offline = value
self._callback(value)
offline_state = OfflineState(cfg.doStuffWhenOfflineVarChanges)
import requests
import datetime
def logEntrance(barCode, noOfGuests, dt=datetime.now()):
date = dt.strftime("%Y-%m-%d")
time = dt.strftime("%H:%M:%S")
headers = {'Content-type': 'application/json', 'Authorization': cfg.auth}
url = 'https://xxxxx.xxxxxxxx.xxx/' + cfg.customerId + '/api.ashx'
params = {"inputtype": "logentrances"}
pl = [{"Barcode": barCode , "PoeID": cfg.poeId, "UserID": cfg.userId, "EntranceDate": date, "EntranceTime": time, "NoOfGuests": str(noOfGuests), "OfflineMode": offline_state.offline}]
try:
r = requests.post(url, json=pl, params=params, headers=headers)
except:
offline_state.offline = True
return r

Mock.patch returning MagicMock object causing AssertionError?

I have a function that I am trying to test in querySomething.py:
class QuerySomething:
def retrieveIssues(self,token):
responses = []
if "customFields" in self._event:
if not self.custom_fields:
fields = []
else:
fields = self.custom_fields
else:
fields = []
for issueTypeKey, issueTypeValue in self.issueTypes.items():
print(issueTypeKey, ":", issueTypeValue)
query = self.getQuery(issueTypeValue, self.status, fields)
respons = httpClient.get_request(query, token)
responses.append(respons)
return responses
And the test file:
def mock_getQuery():
return "QUERY"
def mock_response(state):
if state=="unauth":
with open("src/tests/mockdata/unauthorized_api_response.json","r") as response_file:
unauth_error = response_file.read()
return json.dumps(unauth_error)
elif state=="auth":
with open("src/tests/mockdata/success_api_response.json","r") as response_file:
success_message = response_file.read()
return json.dumps(success_message)
return "No message"
class test_query(unittest.TestCase):
#mock.patch("querySomething.QuerySomething.getQuery", side_effect=mock_getQuery)
#mock.patch("httpClient.get_request", side_effect=mock_response)
def test_retreiveIssues_unauth_response(self,mock_get,QuerySomething):
self.assertEqual(QuerySomething.retrieveIssues("token"),mock_response("unauth"))
if __name__ == "__main__":
unittest.main()
I am trying to mock the httpClient.get_request so that it gets the JSON file instead of reaching out to the API. We want to test an unauthorized response and a success response which explains the mock_response function. However, when I run the test, I get the following:
AssertionError: <MagicMock name='getQuery.retri[36 chars]712'> != '"{\\n \\"errorMessages\\": [\\n [131 chars]\n}"'
which is somewhat correct, but we need just the text, not the object. I read that I need to call the function, but when I try to call the function it throws a ModuleNotFound or NotAPackage error. What do I need to do to mock the httpClient.get_request and return the JSON string in the retrieveIssues function?
Updated, I was able to pull the JSON from the other file, and then was able to mock the return value as follows:
QuerySomething.retrieveIssues.return_value=load_json("unauth")
where load_json("unauth") pulls from the JSON response file.

Updating multiple attributes of a python object - unit testing

import requests
class RadioInfo:
def __init__(self, url, station_num=0):
self.url = url
self.station_num = station_num
def update(self):
radio_info = self.get_json()
self.update_info(radio_info)
def get_json(self):
r = requests.get(self.url)
return r.json()[self.station_num]
def update_info(self, radio_info):
self.radio_station_name = radio_info["station"]["name"]
self.radio_station_description = radio_info["station"]["description"]
self.current_listeners = radio_info["listeners"]["current"]
self.unique_listeners = radio_info["listeners"]["unique"]
self.total_listeners = radio_info["listeners"]["total"]
self.now_playing_playlist = radio_info["now_playing"]["playlist"]
self.now_playing_song_title = radio_info["now_playing"]["song"]["title"]
self.now_playing_song_artist = radio_info["now_playing"]["song"]["artist"]
self.now_playing_song_album = radio_info["now_playing"]["song"]["album"]
###
# What if radio["playing_next"] is None ??
###
self.next_playing_playlist = radio_info["playing_next"]["playlist"]
self.next_playing_song_title = radio_info["playing_next"]["song"]["title"]
self.next_playing_song_artist = radio_info["playing_next"]["song"]["artist"]
self.next_playing_song_album = radio_info["playing_next"]["song"]["album"]
Having the above, trying to figure out how to refactor this, so that I can check if some of the nodes are None and handle this accordingly.
Additionally starting out with unit testing, and besides error handling was thinking about best practices of unit testing this object.
Should I create a method for each property and unit test with pytest.mark.parametrize for example, or is this considered redundant and not necessary ?

Unittest: mock a python class with init method

I am trying to test a run method in my class which has init method and takes object as parameter from another class:
class ServePlate(FreeSurferStep):
process_name = "FreeSurfer"
step_name = "ServePlate"
step_cli = "serve"
cpu = 1
mem = 1024
def __init__(self, project, code, args):
super(Stage, self).__init__(project, code, args)
self.next_step = Autorecon1
#classmethod
def get_queue(cls, project_name):
plog = ProcessingLog()
available = plog.get_project_images(project_name, "T1")
attempted = plog.get_step_attempted(project_name, cls.process_name, cls.step_name)
attempted_codes = [row.Code for row in attempted]
todo = [{'ProjectName': project_name, 'Code': row.Code} for row in available if row.Code not in attempted_codes]
return todo
def run(self): #<<<<-- This method is to be tested
source = None
image = ProcessingLog().get_project_image(self.project, self.code)
if image.ImageStore == "Dicom":
dcmtmp = tempfile.mkdtemp()
DicomRepository().fetch_dicoms(self.code, dcmtmp)
first_t1 = os.path.join(dcmtmp, os.listdir(dcmtmp)[0])
niitmp = os.path.join(tempfile.mkdtemp(), 'raw.nii')
cmd = 'dcm2niix -b n -z n -g i -o {} -f raw {}'.format(os.path.dirname(niitmp), first_t1)
self._run_fs_cmd(cmd)
source = niitmp
elif image.ImageStore == "Pre-Processed":
source = [PreProcessedImageRepository().get_image(self.code), ]
if source is None:
raise ProcessingError("Could not find staging data.")
first_t1 = self._copy_files(source)
cmd = 'recon-all -s %(code)s -i %(image)s' % {
"code": self.code,
"image": first_t1
}
self._run_fs_cmd(cmd). #<<<-- I am trying to check value of cmd variable
Here is my test, i am patching first the init method and second _run_fs_cmd frm another class.
class Testfs(unittest.TestCase):
#patch.object(fs.FreeSurferStep, '_run_fs_cmd', spec=True)
# #patch.object(fs.FreeSurferStep, '__init__')
def test_serve(mock_serve):
"""
Serve step test
"""
mock_serve.project = 'TEST_FS'
mock_serve.code = 'Test9001-1a5'
mock_serve.args = ''
mock_stage.return_value = None
FsObj = FreeSurferStep('serve')
stage_obj = Stage(FsObj)
FsObj.run()
#
# stage_obj.run(self)
#
# self.assertEqual(self.cmd, '')
# fs.FreeSurferStep._run_fs_cmd = Mock()
this gives me error. Here even though i am passing no arguments to the run method, it keeps on complaining about more argument being passed. Also patching a class object to be passed to ServePlate method and patching run_fsmethod where the cmd is passed to doesn't seem to work. Do i need to compulsorily mock all other methods being called?
TypeError: test_serve() takes 1 positional argument but 2 were given
TypeError: run() takes 1 positional argument but 3 were given
i got the test working with initializing correctly:
class Testfs(unittest.TestCase):
project = 'TEST'
code = '9001-1a5'
args = 'nogrid'
#patch.object(fs.FreeSurferStep, '_run_fs_cmd', 'put_object', spec=True)
#patch.object(fs.FreeSurferStep, '__init__')
def test_serve(self, mock_test_serve):
"""
Stage step test
"""
mock_test_stage.return_value = None
project = 'TEST'
code = '9001-1a5'
args = 'nogrid'
self.logger = logging.getLogger(__name__)
FsObj = fs.FreeSurferStep('Stage')
stage_obj = fs.Stage(FsObj, code, args)
stage_obj.project = 'Test'
stage_obj.code = '9001-1a5'
stage_obj.run()
however havent got a way to check value passed to `_run_fs_cmd` method

Django unittest and mocking the requests module

I am new to Mock and am writing a unit test for this function:
# utils.py
import requests
def some_function(user):
payload = {'Email': user.email}
url = 'http://api.example.com'
response = requests.get(url, params=payload)
if response.status_code == 200:
return response.json()
else:
return None
I am using Michael Foord's Mock library as part of my unit test and am having difficulty mocking the response.json() to return a json structure. Here is my unit test:
# tests.py
from .utils import some_function
class UtilsTestCase(unittest.TestCase):
def test_some_function(self):
with patch('utils.requests') as mock_requests:
mock_requests.get.return_value.status_code = 200
mock_requests.get.return_value.content = '{"UserId":"123456"}'
results = some_function(self.user)
self.assertEqual(results['UserId'], '123456')
I have tried numerous combinations of different mock settings after reading the docs with no luck. If I print the results in my unit test it always displays the following instead of the json data structure I want:
<MagicMock name=u'requests.get().json().__getitem__().__getitem__()' id='30315152'>
Thoughts on what I am doing wrong?
Patch json method instead of content. (content is not used in some_function)
Try following code.
import unittest
from mock import Mock, patch
import utils
class UtilsTestCase(unittest.TestCase):
def test_some_function(self):
user = self.user = Mock()
user.email = 'user#example.com'
with patch('utils.requests') as mock_requests:
mock_requests.get.return_value = mock_response = Mock()
mock_response.status_code = 200
mock_response.json.return_value = {"UserId":"123456"}
results = utils.some_function(self.user)
self.assertEqual(results['UserId'], '123456')
Another pattern I like to use that is a little more reusable would be to start the patcher in your unit test's setUp method. It's also important to check that mock request was called with the expected parameters:
class UtilsTestCase(TestCase):
def setUp(self):
self.user = Mock(id=123, email='foo#bar.com')
patcher = patch('utils.requests.get')
self.mock_response = Mock(status_code=200)
self.mock_response.raise_for_status.return_value = None
self.mock_response.json.return_value = {'UserId': self.user.id}
self.mock_request = patcher.start()
self.mock_request.return_value = self.mock_response
def tearDown(self):
self.mock_request.stop()
def test_request(self):
results = utils.some_function(self.user)
self.assertEqual(results['UserId'], 123)
self.mock_request.assert_called_once_with(
'http://api.example.com'
payload={'Email': self.user.email},
)
def test_bad_request(self):
# override defaults and reassign
self.mock_response.status_code = 500
self.mock_request.return_value = self.mock_response
results = utils.some_function(self.user)
self.assertEqual(results, None)
self.mock_request.assert_called_once_with(
'http://api.example.com'
payload={'Email': user.email},
)
Another way that I believe is more clear and straight forward:
import unittest
from mock import Mock, patch
import utils
class UtilsTestCase(unittest.TestCase):
def test_some_function(self):
mock_response = Mock()
mock_response.status_code = 200
mock_response.json.return_value = {"UserId": "123456"}
with patch('utils.requests.get') as mock_requests:
results = utils.some_function(self.user)
self.assertEqual(results['UserId'], '123456')

Categories

Resources