如何在Django/Python中Mock返回响应的URL路径?
几种可行的实现方案
方案1:直接拦截requests.get调用(最简便)
不用搭建真实服务器,直接用unittest.mock拦截指定URL的请求,返回预设的mock响应即可。
示例代码:
import json from unittest.mock import patch import requests import pytest # 你的待测试函数 def get_some_data(api_url, **kwargs): headers = kwargs.get("headers", {}) params = kwargs.get("params", {}) response = requests.get(api_url, headers=headers, params=params) return response # 你的mock响应生成函数(补全bytes编码细节) def mock_response(data): response = requests.Response() response.status_code = 200 response._content = json.dumps(data).encode('utf-8') return response # 测试用例 @pytest.mark.parametrize("test_url, mock_data", [ ("http://mock-api.local/test-data", {"status": "ok", "data": [1,2,3]}), ]) @patch("requests.get") def test_get_some_data(mock_get, test_url, mock_data): # 设定规则:当请求test_url时返回mock响应 mock_get.return_value = mock_response(mock_data) # 调用待测试函数 response = get_some_data(test_url) # 验证结果 assert response.status_code == 200 assert json.loads(response.content) == mock_data # 确认requests.get确实用指定URL调用过 mock_get.assert_called_once_with(test_url, headers={}, params={})
方案2:用Django测试服务器(适合Django项目)
如果是Django项目,直接用Django自带的测试框架启动临时服务器,临时注册一个返回mock数据的视图,就能拿到真实可访问的URL。
示例代码:
from django.http import JsonResponse from django.urls import path from django.test import TestCase import requests import json # 你的待测试函数 def get_some_data(api_url, **kwargs): headers = kwargs.get("headers", {}) params = kwargs.get("params", {}) response = requests.get(api_url, headers=headers, params=params) return response # 临时定义返回mock数据的视图 def mock_api_view(request): return JsonResponse({"source": "django-test-server", "data": "mock-content"}) class TestGetSomeData(TestCase): @classmethod def setUpClass(cls): super().setUpClass() # 临时添加URL路由到项目根URLconf from django.conf import settings root_urlconf = __import__(settings.ROOT_URLCONF, fromlist=["urlpatterns"]) cls.temp_route = path("mock-api/", mock_api_view) root_urlconf.urlpatterns.append(cls.temp_route) @classmethod def tearDownClass(cls): # 测试结束后清理临时路由 from django.conf import settings root_urlconf = __import__(settings.ROOT_URLCONF, fromlist=["urlpatterns"]) root_urlconf.urlpatterns.remove(cls.temp_route) super().tearDownClass() def test_get_some_data(self): # 拼接测试服务器的完整URL test_url = self.live_server_url + "/mock-api/" response = get_some_data(test_url) assert response.status_code == 200 assert json.loads(response.content) == {"source": "django-test-server", "data": "mock-content"}
方案3:用Python标准库启动临时HTTP服务器
如果想要真实可访问的URL而非mock拦截,用Python内置的http.server启动临时服务器,测试完成后自动关闭。
示例代码:
import json import threading from http.server import BaseHTTPRequestHandler, HTTPServer import requests import pytest # 你的待测试函数 def get_some_data(api_url, **kwargs): headers = kwargs.get("headers", {}) params = kwargs.get("params", {}) response = requests.get(api_url, headers=headers, params=params) return response # 定义处理请求的类,返回mock数据 class MockRequestHandler(BaseHTTPRequestHandler): def do_GET(self): self.send_response(200) self.send_header("Content-Type", "application/json") self.end_headers() self.wfile.write(json.dumps({"source": "std-lib-server", "data": "mock-result"}).encode('utf-8')) # 定义pytest fixture,自动启动/关闭服务器 @pytest.fixture(scope="function") def mock_server_url(): server = HTTPServer(("localhost", 0), MockRequestHandler) server_thread = threading.Thread(target=server.serve_forever) server_thread.daemon = True server_thread.start() # 返回服务器完整URL(端口自动分配) yield f"http://localhost:{server.server_address[1]}" # 测试结束后关闭服务器 server.shutdown() # 测试用例 def test_get_some_data(mock_server_url): response = get_some_data(mock_server_url) assert response.status_code == 200 assert json.loads(response.content) == {"source": "std-lib-server", "data": "mock-result"}
内容的提问来源于stack exchange,提问作者octav
相关产品推荐
相关产品推荐

