【发布时间】: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=200和mock.return_value.content=...
标签: python django testing django-rest-framework mocking