Python 如何在Django测试中模拟函数内部使用的API请求?

Python 如何在Django测试中模拟函数内部使用的API请求?,python,django,unit-testing,mocking,pytest,Python,Django,Unit Testing,Mocking,Pytest,我有一个这样构建的小实用程序函数,用于从另一个应用程序API获取数据: # app/utils.py import json import requests from django.conf import settings def get_future_assignments(user_id): """gets a users future assignments list from the API Arguments: us

我有一个这样构建的小实用程序函数,用于从另一个应用程序API获取数据:

# app/utils.py

import json

import requests
from django.conf import settings

def get_future_assignments(user_id):
    """gets a users future assignments list from the API

    Arguments:
        user_id {int} -- user_id for a User
    """
    headers = {
        "User-Agent": "Mozilla/5.0",
        "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
        "X-Requested-With": "XMLHttpRequest",
    }
    api_app = settings.ASSIGNMENTS_API_ROOT_URL # http://project.org/appname/
    api_model = "futureassignments/"
    api_query = "?user_id=" + str(user_id)
    json_response = requests.get(
        api_app + api_model + api_query, headers=headers, verify=False
    )
    return json.loads(json_response.content)
它基本上构建API调用并返回响应数据——我想对此进行测试

# tests/test_utils.py

import mock
from unittest.mock import patch, Mock
from django.test import TestCase

from app.utils import get_future_assignments

class UtilsTest(TestCase):
    def setUp(self):
        self.futureassignments = [
            {
                "id": 342,
                "user_id": 18888,
                "job": 361,
                "location": "1234",
                "building": "Building One",
                "confirmed_at": None,
                "returning": None,
                "signature": None,
            },
            {
                "id": 342,
                "user_id": 18888,
                "job": 361,
                "location": "1235",
                "building": "Building Two",
                "confirmed_at": None,
                "returning": None,
                "signature": None,
            },
        ]

    @patch("app.utils.get_future_assignments")
    def test_get_future_assignments_with_multi_assignments(self, mock_gfa):
        """
        Test for getting future assignments for a user with mocked API
        """
        mock_gfa.return_value = Mock()
        # set the json response to what we're expecting
        mock_gfa.return_value.json.return_value = self.futureassignments
        assignments = get_future_assignments(18888)
        self.assertEqual(len(assignments), 2)
它不断给我一个错误,它无法到达API以获得响应(这是目前所期望的-因为我在本地运行它,它无法到达API)

我对使用Mock还不熟悉,所以也许我在这里有点太离谱了


有什么想法吗?

像你一样,我也不熟悉使用
mock
。我相信它的目的是这样:

    @patch("requests.get")
    def test_get_future_assignments_with_multi_assignments(self, mock_requests_get):
        """
        Test for getting future assignments for a user with mocked API
        """
        mock_requests_get.return_value = json.dumps(self.futureassignments)
        assignments = get_future_assignments(18888)
        self.assertEqual(len(assignments), 2)

如果我错了,请纠正我

因为您想要模拟API响应,所以应该修补
requests.get
函数,而不是您自己想要测试的函数。目前这个测试有点愚蠢(即使您模拟了请求)。因为您正在测试不使用的设置头和内置json解析模拟响应的能力。那么Melvyn-您将如何更改它?持批评态度,不提供任何方法来帮助改善局面或使事情变得更好是。。。没用,谢谢!