I am trying to unit test some of my functions using mocks in python. Few of them seems to be working as expected but I am trouble with the response of one the test case. Which it not returning the ideal response which it should.
###############motpenrichreceiverinfo.py##################
import requests
def getReceiverInfo(fundId):
print('Inside fetchReceiverInfo',fundId)
response = requests.get("REST URL FOR RECEIVER INFO")
if response.ok:
return response
else:
return None
def getMotpTrade(trade_id):
response = requests.get("REST URL")
if response.ok:
return response
else:
return None
def getMotpCanonical(trade_id):
response = requests.get("REST URL")
if response.ok:
return response
else:
return None
def EnrichTradeWithReceiverInfo(event, context):
#print('Lambda function started..')
trade_id = event['tradeId']
motpTrade = getMotpTrade(trade_id)
canonicalTrade = getMotpCanonical(trade_id)
fundId = motpTrade['Account']
#print(fundId)
data = getReceiverInfo(fundId)
print(data)
return data
##########################test_motptrade.py##############################
# Standard library imports
from unittest.mock import Mock, patch
# Third-party imports...
from nose.tools import assert_true
from nose.tools import assert_is_not_none, assert_list_equal, assert_dict_equal
# Local imports
from motpenrichreceiverinfo import getMotpTrade, getReceiverInfo, EnrichTradeWithReceiverInfo
@patch('motpenrichreceiverinfo.requests.get')
def test_motptraderequest_response(mock_get):
motpTrade = [{
"motpTrade":"motpTrade"
}]
# Configure the mock to return a response with an OK status code.
mock_get.return_value.ok = True
mock_get.return_value.json.return_value = motpTrade
# Send a request to the API server and store the response.
response = getMotpTrade('tradeId')
# If the request is sent successfully, then I expect a response to be returned.
assert_list_equal(response.json(), motpTrade)
@patch('motpenrichreceiverinfo.requests.get')
def test_getReceiverInfo_respose_ok(mock_get):
receiverInfo = [{
"reciever":"reciever"
}]
# Configure the mock to return a response with an OK status code.
mock_get.return_value.ok = True
mock_get.return_value.json.return_value = receiverInfo
# Send a request to the API server and store the response.
response = getReceiverInfo("1110")
# If the request is sent successfully, then I expect a response to be returned.
assert_list_equal(response.json(), receiverInfo)
@patch('motpenrichreceiverinfo.getMotpTrade')
@patch('motpenrichreceiverinfo.getMotpCanonical')
@patch('motpenrichreceiverinfo.getReceiverInfo')
def test_EnrichTradeWithReceiverInfo_ok(mock_get,mock_canonical,mock_receiverinfo):
motpTrade = [{
"motpTrade":"motpTrade"
}]
receiverInfo = [{
"reciever":"reciever"
}]
event = {"tradeId":"123456"}
# Configure the mock to return a response with an OK status code.
mock_get.return_value = Mock(ok=True)
mock_get.return_value.json.return_value = motpTrade
mock_canonical.return_value.ok = True
mock_canonical.return_value.json.return_value = [{}]
mock_receiverinfo.return_value.ok = True
mock_receiverinfo.return_value.json.return_value = receiverInfo
data = EnrichTradeWithReceiverInfo(event,"")
assert_true(mock_get.called)
assert_true(mock_receiverinfo.called)
assert_list_equal(data.json(),receiverInfo)
Here my first two cases are working as expected. But my last test case(test_EnrichTradeWithReceiverInfo_ok) is somehow not working. Ideally it should have response equal to receiverInfo object.But when I run it gives below error. It would be really helpful someone can help me understand what I am doing wrong here.
(venv) C:\Development\motplambdas>nosetests -v test_motptrade.py
test_motptrade.test_EnrichTradeWithReceiverInfo_ok ... FAIL
test_motptrade.test_getReceiverInfo_respose_ok ... ok
test_motptrade.test_motptraderequest_response ... ok
======================================================================
FAIL: test_motptrade.test_EnrichTradeWithReceiverInfo_ok
----------------------------------------------------------------------
Traceback (most recent call last):
File "c:\development\motplambdas\venv\lib\site-packages\nose\case.py", line 198, in runTest
self.test(*self.arg)
File "c:\program files\python38\lib\unittest\mock.py", line 1325, in patched
return func(*newargs, **newkeywargs)
File "C:\Development\motplambdas\test_motptrade.py", line 69, in test_EnrichTradeWithReceiverInfo_ok
assert_list_equal(data.json(),receiverInfo)
AssertionError: Lists differ: [{'motpTrade': 'motpTrade'}] != [{'reciever': 'reciever'}]
First differing element 0:
{'motpTrade': 'motpTrade'}
{'reciever': 'reciever'}
- [{'motpTrade': 'motpTrade'}]
+ [{'reciever': 'reciever'}]
----------------------------------------------------------------------
Ran 3 tests in 0.011s
FAILED (failures=1)
The issue is the order of which you are passing your Mock
objects into the function call.
@patch('motpenrichreceiverinfo.getMotpTrade')
@patch('motpenrichreceiverinfo.getMotpCanonical')
@patch('motpenrichreceiverinfo.getReceiverInfo')
def test_EnrichTradeWithReceiverInfo_ok(mock_get,mock_canonical,mock_receiverinfo)
Mock
objects are passed from the bottom up, meaning @patch('motpenrichreceiverinfo.getReceiverInfo')
is the first Mock
passed in to the function call, not the last as you have it listed. Due to this you end up setting getReceiverInfo
to return the wrong value. The solution is to switch the function call to look like this:
def test_EnrichTradeWithReceiverInfo_ok(mock_receiverinfo, mock_canonical, mock_get)
You can read more about this here where it explains how nesting decorators works.
Note that the decorators are applied from the bottom upwards. This is the standard way that Python applies decorators. The order of the created mocks passed into your test function matches this order.