在python测试中,模拟时生成的响应是不正确的



我正在尝试使用python中的mock对我的一些函数进行单元测试。他们中似乎很少有人能像预期的那样工作,但我对其中一个测试用例的响应感到困扰。它没有返回理想的反应,它应该。

###############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_mottrade.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) 

在这里,我的前两个案例正在按预期运行。但是我的最后一个测试用例(test_EnrichTradeWithReceiverInfo_ok(不知怎么不起作用。理想情况下,它的响应应该等于receiverInfo对象。但当我运行时,它会给出以下错误。如果有人能帮助我理解我在这里做错了什么,那将非常有帮助。

(venv) C:Developmentmotplambdas>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:developmentmotplambdasvenvlibsite-packagesnosecase.py", line 198, in runTest
self.test(*self.arg)
File "c:program filespython38libunittestmock.py", line 1325, in patched
return func(*newargs, **newkeywargs)
File "C:Developmentmotplambdastest_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)

问题在于将Mock对象传递到函数调用中的顺序。

@patch('motpenrichreceiverinfo.getMotpTrade')
@patch('motpenrichreceiverinfo.getMotpCanonical')
@patch('motpenrichreceiverinfo.getReceiverInfo')
def test_EnrichTradeWithReceiverInfo_ok(mock_get,mock_canonical,mock_receiverinfo)

Mock对象是从下往上传递的,这意味着@patch('motpenrichreceiverinfo.getReceiverInfo')是传递给函数调用的第一个Mock,而不是最后一个。因此,您最终将getReceiverInfo设置为返回错误的值。解决方案是将函数调用切换为如下所示:

def test_EnrichTradeWithReceiverInfo_ok(mock_receiverinfo, mock_canonical, mock_get)

你可以在这里阅读更多关于这方面的内容,它解释了嵌套装饰器是如何工作的。

请注意,装饰器是从底部向上应用的。这是Python应用decorator的标准方式。传递到测试函数中的已创建mock的顺序与此顺序匹配。

最新更新