You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python如何测试Stripe SignatureVerificationError异常处理逻辑

问题场景

对于Python开发,Stripe官方给出的标准Webhook代码示例如下:

event = None
try:
    event = stripe.Webhook.construct_event(payload, sig_header, endpoint_secret)
except ValueError as e:
    logger.error(f"*** Stripe invalid payload: {e = }")
    return HttpResponse(status=400)
except stripe.error.SignatureVerificationError as e:
    logger.error(f"*** Stripe invalid signature: {e = }")
    return HttpResponse(status=400)

编写的继承自Django TestCase的测试用例如下,目的是验证签名验证错误的处理逻辑:

class TestStripeWebhookView(TestCase):
    @mock.patch("logging.Logger.error")
    @mock.patch("lettergun.apps.payments.views.create_order")
    @mock.patch("lettergun.apps.payments.views.stripe")
    def test_signature_verification_error(self, stripe, create_order, error):
        stripe.Webhook.construct_event.side_effect = SignatureVerificationError

        data = {
            "type": "placeholder",
        }

        response = self.client.get(
            reverse("payments:stripe_webhook"),
            data,
            HTTP_ACCEPT="application/json",
            HTTP_STRIPE_SIGNATURE='placeholder_signature"}',
        )

        error.assert_called_with(f"*** Stripe invalid signature: e = an error message")
        assert not create_order.called
        assert response.status_code == 400

运行测试时抛出如下错误:

> except stripe.error.SignatureVerificationError as e:
E TypeError: catching classes that do not inherit from BaseException is not allowed
错误原因

报错核心原因是用@mock.patch("lettergun.apps.payments.views.stripe")替换了视图文件中引入的整个stripe模块,此时视图代码里访问的stripe.error.SignatureVerificationError不再是Stripe SDK提供的真实异常类,而是mock生成的MagicMock实例。Python规定except关键字后跟随的异常类必须继承自BaseException,MagicMock不满足这个要求,因此抛出类型错误。

除此之外原测试代码还有两个逻辑问题:

  • 给side_effect赋值时直接传了SignatureVerificationError类引用,没有正确导入真实类也没有实例化,即使mock范围正确也无法正确触发异常捕获逻辑
  • 测试Webhook接口用了GET请求,而Stripe的Webhook回调只会发送POST请求
修正方案
  • 不要全量mock整个stripe模块,只mock需要替换行为的stripe.Webhook.construct_event方法,保留stripe其他属性(包括异常类)的真实实现
  • 触发异常时传入真实实例化的stripe.error.SignatureVerificationError对象,该异常构造需要传入两个必填参数:错误信息、请求签名头内容
  • 把测试请求改为POST请求,符合Stripe Webhook的实际调用逻辑

修正后的测试代码参考:

import stripe
# 其余导入省略:TestCase、mock、reverse、视图相关依赖等

class TestStripeWebhookView(TestCase):
    @mock.patch("logging.Logger.error")
    @mock.patch("lettergun.apps.payments.views.create_order")
    # 仅mock需要替换逻辑的construct_event方法,不mock整个stripe模块
    @mock.patch("lettergun.apps.payments.views.stripe.Webhook.construct_event")
    def test_signature_verification_error(self, mock_construct_event, mock_create_order, mock_log_error):
        test_sig = 'placeholder_signature'
        # 抛出真实实例化的签名验证异常
        mock_construct_event.side_effect = stripe.error.SignatureVerificationError(
            "an error message",
            test_sig
        )

        data = {
            "type": "placeholder",
        }

        # 改用POST请求发起测试
        response = self.client.post(
            reverse("payments:stripe_webhook"),
            data=data,
            content_type="application/json",
            HTTP_STRIPE_SIGNATURE=test_sig,
        )

        mock_log_error.assert_called_with(f"*** Stripe invalid signature: e = an error message")
        assert not mock_create_order.called
        assert response.status_code == 400

内容的提问来源于stack exchange,提问作者John

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 16:12:28