对python函数的异常测试感到困惑吗

对python函数的异常测试感到困惑吗,python,exception,python-unittest,python-unittest.mock,Python,Exception,Python Unittest,Python Unittest.mock,我有一个功能process\u payment,我想对其进行异常测试: def process_payment(event, context): try: payDictionary= json.loads(event["body"]) if "payment_method_id" in payDictionary: intent = stripe.PaymentIntent.create(

我有一个功能
process\u payment
,我想对其进行异常测试:

def process_payment(event, context):

    try:
        payDictionary= json.loads(event["body"])
        if "payment_method_id" in payDictionary:
            intent = stripe.PaymentIntent.create(
                payment_method = payDictionary['payment_method_id'], 
                amount = 1000, 
                currency = 'usd',
                payment_method_types=["card"]
                )
            print(intent.status)
            if intent.status == 'succeeded':
                return {
                        "statusCode": 200,
                        "body": json.dumps({
                            'message': 'Payment succeeded',
                        }),
                    }          
    except Exception as e:
        return {
                "body": json.dumps({
                    "message": 'Payment failed. '+ str(e),
                }),
            }
我想对上述函数进行异常测试,因此我使用unittests框架编写了以下代码进行测试:

import unittest
from unittest import mock
from unittest.mock import patch, Mock
import json
import stripe
from stripe.util import convert_to_stripe_object
from . import app

       def test_process_payment_exception(self):
            event = {
                'httpMethod': 'POST', 
                'body': '{"payment_method_id":"pm_1HGTb2GPqNNATumTCzrTXZ9e"}'
                }
           
            response = {}            
    
            with mock.patch('stripe.PaymentIntent.create', side_effect= Exception) as mock_process_payment:
                stripe_obj = convert_to_stripe_object(response)
                mock_process_payment.return_value= stripe_obj
                self.assertRaises(Exception, app.process_payment, event, "")
此测试代码产生以下响应:

======================================================================
FAIL: test_process_payment_exception (hello_world.test_app.TestStudent)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\Users\...\sam-app\hello_world\test_app.py", line 524, in test_process_payment_exception
    app.process_payment(event, "")
AssertionError: Exception not raised

----------------------------------------------------------------------
Ran 2 tests in 0.024s

FAILED (failures=1)
Traceback (most recent call last):
  File "C:\Users\...\sam-app\hello_world\test_app.py", line 536, in test_process_payment_exception
    ....
......
+ Payment failed. mock_method() got an unexpected keyword argument 'payment_method'

-------------------- >> begin captured stdout << ---------------------
Payment failed. mock_method() got an unexpected keyword argument 'payment_method'

--------------------- >> end captured stdout << ----------------------

----------------------------------------------------------------------
Ran 2 tests in 0.024s

FAILED (failures=1)
我正在努力找出如何在不对原始代码进行额外更改的情况下对该函数进行异常测试

编辑:

我将代码更改为如下所示:

def测试\流程\付款\异常(自身):
事件={
“httpMethod”:“POST”,
'正文':'{“付款方法id:“pm_1HGTB2GPQNNATUMTCZRTX9E”}'
}
def mock_方法():
引发异常(“someMessage”)
使用mock.patch('stripe.PaymentIntent.create')作为模拟付款流程:
stripe_obj=将_转换为_stripe_对象(响应)
模拟过程支付。副作用=模拟方法
ret=应用程序处理\付款(事件“”)
打印(ret)
getmessage=json.load(ret['body'])
getmessageFinal=getmessage[“message”]
self.assertEqual(“someMessage”,getmessageFinal)
这就产生了以下反应:

======================================================================
FAIL: test_process_payment_exception (hello_world.test_app.TestStudent)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\Users\...\sam-app\hello_world\test_app.py", line 524, in test_process_payment_exception
    app.process_payment(event, "")
AssertionError: Exception not raised

----------------------------------------------------------------------
Ran 2 tests in 0.024s

FAILED (failures=1)
Traceback (most recent call last):
  File "C:\Users\...\sam-app\hello_world\test_app.py", line 536, in test_process_payment_exception
    ....
......
+ Payment failed. mock_method() got an unexpected keyword argument 'payment_method'

-------------------- >> begin captured stdout << ---------------------
Payment failed. mock_method() got an unexpected keyword argument 'payment_method'

--------------------- >> end captured stdout << ----------------------

----------------------------------------------------------------------
Ran 2 tests in 0.024s

FAILED (failures=1)
回溯(最近一次呼叫最后一次):
文件“C:\Users\…\sam app\hello\u world\test\u app.py”,第536行,在test\u process\u payment\u exception中
....
......
+付款失败。mock_method()获得意外的关键字参数“payment_method”

-------------------->>开始捕获标准输出>结束捕获标准输出您的第二个变体几乎是正确的。问题在于,使用与原始方法相同的参数调用副作用(
create
),例如,它的调用方式如下:

mock_方法(付款方法、金额、货币等)
(所有这些都是关键字参数)。As
mock_方法
没有关键字 如果定义了参数,则会收到错误消息(只提到第一个缺少的参数)

来自(强调的相关部分):

副作用:在调用Mock时调用的函数。请参见“副作用”属性。用于引发异常或动态更改返回值使用与模拟相同的参数调用该函数,除非返回默认值,否则将使用此函数的返回值作为返回值

因此,您必须考虑这些参数。如果您对实际参数不感兴趣,可以使用通用符号
*args,**kwargs
,其中
args
表示所有位置参数(作为列表)和
kwargs
所有kwyword参数(作为dict)

在您的情况下,这就足够了:

def测试\流程\付款\异常(自身):
事件={
“httpMethod”:“POST”,
'正文':'{“付款方法id:“pm_1HGTB2GPQNNATUMTCZRTX9E”}'
}
def模拟_方法(*args,**kwargs):
引发异常(“提供的PaymentMethod…”)
使用mock.patch('stripe.PaymentIntent.create')作为模拟付款流程:
stripe_obj=将_转换为_stripe_对象(响应)
...
旁注:“Payment failed:”已由调用代码作为前缀,因此不应将其放入异常

也就是说,在您的情况下,直接将异常分配给
副作用更容易:

使用mock.patch('stripe.PaymentIntent.create')作为模拟付款流程:
模拟流程付款=异常(“someMessage”)
stripe_obj=将_转换为_stripe_对象(响应)

除了分配函数(如上所示)或值列表之外,您还可以直接将异常(而不是异常类)分配给
副作用

您能解释一下为什么我看到消息
mock\u method()得到了一个意外的关键字参数“payment\u method”。
?您能解释一下为什么
(*args,**kwargs)
很重要吗?我添加了更多的解释。哦,如果模拟函数有参数,则必须明确告知
副作用
。是吗?是的,我添加了一个文档链接。