【问题标题】:Mock a test with an external api rest in Django Rest Framework在 Django Rest Framework 中使用外部 api rest 模拟测试
【发布时间】:2020-12-30 20:12:25
【问题描述】:

上下文

我正在使用 Django Rest Framework 开发 API Rest,并且我的一些端点使用外部 API Rest 来创建模型实例,代码可以工作,但现在我正在尝试测试我的代码,但我对此非常挣扎.我是一个开发测试的初学者,也许问题很明显,但是我尝试了很多东西,使用下面的链接但我无法实现。

Mocking external API for testing with Python

How do I mock a third party library inside a Django Rest Framework endpoint while testing?

https://realpython.com/testing-third-party-apis-with-mocks/

代码

这是我的看法

from rest_framework import viewsets, status
from rest_framework.decorators import action
from rest_framework.response import Response
from app.lnd_client import new_address
from app.models import Wallet
from api.serializers import WalletSerializer



class WalletViewSet(viewsets.ModelViewSet):
    queryset = Wallet.objects.all()
    serializer_class = WalletSerializer
    lookup_field = "address"

    @action(methods=["post"], detail=False)
    def new_address(self, request):
        response = new_address()
        if "error" in response.keys():
            return Response(
                data={"error": response["error"]}, status=response["status_code"]
            )
        else:
            return Response(response)

    def create(self, request, *args, **kwargs):

        response = self.new_address(self)
        if response.status_code >= 400:
            return response

        serializer = self.get_serializer(data=response.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        return Response(
            serializer.data, status=status.HTTP_201_CREATED, headers=headers
        )

这是我调用外部 api 的客户

import requests
from django.conf import settings
from typing import Dict

endpoint = settings.LND_REST["ENDPOINT"]
endpoint = endpoint[:-1] if endpoint.endswith("/") else endpoint
endpoint = (
    "https://" + endpoint if not endpoint.startswith("http") else endpoint
)
endpoint = endpoint

auth = {"Grpc-Metadata-macaroon": settings.LND_REST["MACAROON"]}
cert = settings.LND_REST["CERT"]

def new_address() -> Dict:

    try:
        r = requests.get(
            f"{endpoint}/v1/newaddress", headers=auth, verify=cert
        )
        r.raise_for_status()
    except requests.exceptions.HTTPError as errh:
        return {
            "error": errh.response.text,
            "status_code": errh.response.status_code,
        }
    except requests.exceptions.RequestException:
        return {
            "error": f"Unable to connect to {endpoint}",
            "status_code": 500,
        }

    return r.json()

我的测试是这样的

from django.urls import reverse
from nose.tools import eq_
from rest_framework.test import APITestCase
from unittest.mock import patch
from rest_framework import status
from .factories import WalletFactory
from app.lnd_client import new_address

class TestWalletListTestCase(APITestCase):
    def setUp(self):
        WalletFactory.create_batch(5)
        self.url = reverse("wallet-list")
        self.wallet_data = WalletFactory.generate_address()

    def test_get_all_wallets(self):
        response = self.client.get(self.url)
        eq_(response.status_code, status.HTTP_200_OK)

    #This is the problem test
    @patch('app.lnd_client.requests.post')
    def test_create_wallet(self,mock_method):
        mock_method.return_value.ok = True
        response = self.client.post(self.url)
        eq_(response.status_code, status.HTTP_201_CREATED)

【问题讨论】:

  • 您看到的实际问题是什么?看起来您正在正确修补(从导入的角度来看,这很好)。我以同样的方式模拟,但我设置了 mock.return_value.status_code=200mock.return_value.content=...

标签: python django testing django-rest-framework mocking


【解决方案1】:

看看httmock。它应该做你正在寻找的东西。他们文档中的示例是:

from httmock import urlmatch, HTTMock
import requests

@urlmatch(netloc=r'(.*\.)?google\.com$')
def google_mock(url, request):
    return 'Feeling lucky, punk?'

with HTTMock(google_mock):
    r = requests.get('http://google.com/')

print(r.content)  # 'Feeling lucky, punk?'

你会想要使用类似的东西:

@urlmatch(path=r"(.*)/newaddress$")
def new_address_url(url, request):
    return {...} # stuff

with HTTMock(new_address_url)
    # make request to DRF api here.

【讨论】:

    猜你喜欢
    • 2018-07-06
    • 2016-06-01
    • 2018-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-25
    • 1970-01-01
    • 2014-07-14
    相关资源
    最近更新 更多