【问题标题】:How to mock API request used inside function in a Django test?如何在 Django 测试中模拟函数内部使用的 API 请求?
【发布时间】:2020-12-03 17:48:16
【问题描述】:

我有一个像这样构建的小实用函数来从另一个应用程序 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 的新手 - 所以我可能有点离谱。

有什么想法吗?

【问题讨论】:

  • 既然你想模拟 API 响应,你应该修补 requests.get 函数,不是你自己想要测试的函数。
  • 目前这个测试有点傻(即使你模拟请求)。因为您正在测试不使用的设置标头以及内置 json 解析模拟响应的能力。
  • 那么 Melvyn - 你将如何改变它?批评并没有提供任何帮助改善情况或使事情变得更好的方法是......没有帮助。

标签: python django unit-testing mocking pytest


【解决方案1】:

和你一样,我也是使用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)

如果我错了,请纠正我!

【讨论】:

    猜你喜欢
    • 2019-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多