本文目录导读:

在Python中Mock外部API有多种方法,我来介绍最常用的几种:
使用 unittest.mock(标准库)
patch 装饰器
import requests
from unittest.mock import patch
import unittest
def get_user_data(user_id):
response = requests.get(f'https://api.example.com/users/{user_id}')
return response.json()
class TestUserAPI(unittest.TestCase):
@patch('requests.get')
def test_get_user_data(self, mock_get):
# 设置模拟响应
mock_response = mock_get.return_value
mock_response.status_code = 200
mock_response.json.return_value = {
'id': 1,
'name': 'John Doe',
'email': 'john@example.com'
}
# 调用被测试函数
result = get_user_data(1)
# 验证结果
self.assertEqual(result['name'], 'John Doe')
self.assertEqual(result['email'], 'john@example.com')
# 验证API被正确调用
mock_get.assert_called_once_with('https://api.example.com/users/1')
patch 上下文管理器
import requests
from unittest.mock import patch
def get_temperature(city):
response = requests.get(f'https://api.weather.com/temp/{city}')
if response.status_code == 200:
return response.json()['temperature']
return None
# 使用上下文管理器
with patch('requests.get') as mock_get:
mock_response = mock_get.return_value
mock_response.status_code = 200
mock_response.json.return_value = {'temperature': 25.5}
result = get_temperature('Beijing')
assert result == 25.5
手动创建Mock对象
from unittest.mock import Mock, patch
import requests
def process_external_api(url, data):
response = requests.post(url, json=data)
return response.json()
# 创建完整的Mock响应
mock_response = Mock()
mock_response.status_code = 201
mock_response.json.return_value = {'status': 'success', 'id': 123}
with patch('requests.post', return_value=mock_response):
result = process_external_api('https://api.example.com/data', {'key': 'value'})
print(result) # {'status': 'success', 'id': 123}
使用第三方库
使用 responses 库
import responses
import requests
@responses.activate
def test_api():
# 注册模拟响应
responses.add(
responses.GET,
'https://api.example.com/users/1',
json={'id': 1, 'name': 'John'},
status=200
)
# 调用实际的requests
response = requests.get('https://api.example.com/users/1')
data = response.json()
assert data['name'] == 'John'
assert response.status_code == 200
使用 mocket 库
from mocket import Mocket, mocketize
import requests
@mocketize
def test_with_mocket():
# 注册模拟响应
Mocket.register(
url='https://api.example.com/users',
method='GET',
body='{"users": ["Alice", "Bob"]}',
headers={'Content-Type': 'application/json'}
)
# 正常的requests调用
response = requests.get('https://api.example.com/users')
data = response.json()
assert data['users'] == ['Alice', 'Bob']
高级Mock技巧
Mock带认证的API
from unittest.mock import patch
class APIClient:
def __init__(self, token):
self.token = token
self.session = requests.Session()
self.session.headers.update({'Authorization': f'Bearer {token}'})
def get_data(self):
response = self.session.get('https://api.example.com/data')
return response.json()
def test_api_client():
with patch.object(requests.Session, 'get') as mock_get:
mock_response = mock_get.return_value
mock_response.json.return_value = {'data': 'test'}
client = APIClient('fake_token')
result = client.get_data()
assert result['data'] == 'test'
mock_get.assert_called_once_with('https://api.example.com/data')
Mock异步API调用
import aiohttp
import asyncio
from unittest.mock import AsyncMock, patch
async def fetch_data(url):
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
return await response.json()
# 测试异步函数
@pytest.mark.asyncio
async def test_fetch_data():
with patch('aiohttp.ClientSession.get') as mock_get:
# 创建异步mock
mock_context = AsyncMock()
mock_get.return_value = mock_context
mock_response = AsyncMock()
mock_response.json = AsyncMock(return_value={'data': 'test'})
mock_context.__aenter__.return_value = mock_response
result = await fetch_data('https://api.example.com/data')
assert result['data'] == 'test'
最佳实践建议
使用配置驱动的Mock
# mock_config.py
MOCK_RESPONSES = {
'GET': {
'https://api.example.com/users/1': {
'status': 200,
'json': {'id': 1, 'name': 'John'}
},
'https://api.example.com/users/2': {
'status': 404,
'json': {'error': 'User not found'}
}
},
'POST': {
'https://api.example.com/users': {
'status': 201,
'json': {'id': 3, 'name': 'New User'}
}
}
}
# test.py
import requests
from unittest.mock import patch
def mock_api_call(method, url, **kwargs):
"""通用API mock函数"""
config = MOCK_RESPONSES.get(method, {}).get(url, {})
response = Mock()
response.status_code = config.get('status', 200)
response.json.return_value = config.get('json', {})
return response
# 使用
with patch('requests.get', side_effect=mock_api_call):
result = requests.get('https://api.example.com/users/1')
print(result.json()) # {'id': 1, 'name': 'John'}
选择建议
- 简单测试:使用
unittest.mock.patch - 复杂API:使用
responses或requests-mock - 异步API:使用
AsyncMock - 开发环境:考虑用
VCR.py录制真实响应
Mock的关键是只模拟外部依赖,保持内部逻辑的真实性,这样测试才会真正验证代码的正确性。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播