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

问题描述

我正在尝试使用 python 中的模拟对我的一些函数进行单元测试。他们中的几个似乎按预期工作,但我对一个测试用例的响应感到困难。它没有返回它应该返回的理想响应。

###############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,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:\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)

解决方法

问题在于您将 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_get)

您可以阅读有关此 here 的更多信息,其中解释了嵌套装饰器的工作原理。

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

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...