用Django测试中的JSON对象替换对外部资源的请求

问题描述 投票:2回答:1

我有一个API

import stripe

class StripeWebHook(APIView):
    permission_classes = (AllowAny,)
    authentication_classes = ()

    def post(self, request, *args, **kwargs):
        payload = request.body
        try:
            event = stripe.Event.construct_from(
                json.loads(payload), stripe.api_key
            )
        except ValueError as e:
            return Response(status=400)

如何使用patch编写测试以测试对外部API(例如stripe.Event.create)的请求,而无需从我的主函数转移该函数调用?

我设法通过如下重写功能来对其进行测试:

def get_api_result(payload):
  return stripe.Event.construct_from(
            json.loads(payload), stripe.api_key
        )

class StripeWebHook(APIView):
    def post(self):
      payload = request.body
      res = get_api_result(payload)
      # ...

并使用mock

import mock
@mock.patch('get_api_result')
def test_payment(self, mockEvent) -> None:
    #...
    mockEvent.return_value = obj

但是我不喜欢这种方法。我不得不添加另一个函数来模拟它似乎并不正确。

我尝试过此

import stripe

class StripeWebHookTestCase(APITestCase):    
    @mock.patch('donation.views.stripe.Event.construct_from')
    def test_stripe_web_hook(self, mockEvent) -> None:
        # logic
        mockEvent.return_value = object
        resp = self.client.post(reverse('stripe-web-hook'))

但是我收到错误Expecting value: line 1 column 1 (char 0)

Traceback

  File "/usr/local/lib/python3.7/json/__init__.py", line 348, in loads
    return _default_decoder.decode(s)
  File "/usr/local/lib/python3.7/json/decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/local/lib/python3.7/json/decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

项目的结构

project/
  project/
    donation/
      tests/
        test_view.py   (StripeWebHookTestCase)
      views.py         (StripeWebHook)
    settings/
    manage.py
python django unit-testing mocking python-mock
1个回答
1
投票
您应该可以直接修补stripe.Event.create。只要确保patch it where it's used

patch()通过(暂时)将

name指向的对象更改为另一个对象来工作。可以有许多名称指向任何单个对象,因此要使修补程序起作用,必须确保对被测系统使用的名称进行修补。

基本原理是,您修补对象

向上看

的位置,该位置不一定与定义的位置相同。
例如,类似这样的方法应该起作用:

patch()

我鼓励您阅读上面引用的整个部分。
© www.soinside.com 2019 - 2024. All rights reserved.