Backend Development 8 min read

Introduction to HTTPretty: Mocking HTTP Requests in Python

HTTPretty is a Python library for testing that enables lightweight, precise mocking of HTTP/HTTPS requests and responses, offering isolation, speed, complex scenario simulation, and data protection, illustrated with five practical code examples covering token retrieval, webhook handling, error simulation, timeout testing, and pagination.

Test Development Learning Exchange
Test Development Learning Exchange
Test Development Learning Exchange
Introduction to HTTPretty: Mocking HTTP Requests in Python

HTTPretty is a Python library designed for testing environments, allowing lightweight and precise mocking of HTTP(s) requests and responses without real network connections.

Key advantages include isolating tests from unstable external services, accelerating test cycles, easily simulating edge cases such as timeouts and error status codes, and protecting sensitive data by using mock responses.

The article provides five code examples demonstrating common usage scenarios.

Example 1: Mocking WeChat access_token API response

import requests
from httpretty import HTTPretty, httprettified
# 微信 API 地址
WECHAT_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token"

@httprettified
def test_get_access_token():
    # 预设模拟响应
    expected_response = '{"access_token":"your_token","expires_in":7200}'
    HTTPretty.register_uri(
        HTTPretty.GET,
        WECHAT_TOKEN_URL,
        body=expected_response,
        status=200,
        content_type="application/json",
    )
    # 调用实际获取 access_token 的函数(假设已实现)
    access_token = get_access_token(appid, secret)
    # 断言返回的 access_token 与模拟响应一致
    assert access_token == "your_token"

Example 2: Mocking a user subscription webhook

import json
from httpretty import HTTPretty, httprettified
# 事件处理器 URL
EVENT_HANDLER_URL = "https://your_server.com/wechat/webhook"

@httprettified
def test_handle_subscribe_event():
    # 构造关注事件的 JSON 数据
    event_payload = {
        "ToUserName": "your_appid",
        "FromUserName": "openid",
        "Event": "subscribe",
    }
    HTTPretty.register_uri(
        HTTPretty.POST,
        EVENT_HANDLER_URL,
        body=json.dumps(event_payload),
        content_type="application/json",
    )
    # 调用实际的事件处理器函数(假设已实现)
    handle_subscribe_event(json.dumps(event_payload))
    # 验证处理逻辑,如检查数据库中用户状态是否已更新为已关注
    assert UserSubscription.query.filter_by(openid="openid").one().is_subscribed

Example 3: Simulating a 404 Not Found error

from httpretty import HTTPretty, httprettified
# 需要模拟失败响应的 API 地址
API_URL = "https://api.example.com/resource"

@httprettified
def test_handle_not_found_error():
    HTTPretty.register_uri(
        HTTPretty.GET,
        API_URL,
        status=404,
        body="Resource not found",
        content_type="text/plain",
    )
    # 调用实际请求函数(假设已实现)
    response = make_api_request()
    # 断言请求返回的状态码和处理结果
    assert response.status_code == 404
    assert response.content == b"Resource not found"
    assert error_handling_function(response) is not None

Example 4: Simulating delayed response to test timeout handling

import time
from httpretty import HTTPretty, httprettified
# 需要模拟延迟响应的 API 地址
DELAYED_API_URL = "https://slow-api.example.com/data"

@httprettified
def test_request_timeout_handling():
    HTTPretty.register_uri(
        HTTPretty.GET,
        DELAYED_API_URL,
        body='{"key": "value"}',
        content_type="application/json",
        status=200,
    )
    HTTPretty.enable_net_connect(False)  # 禁止真实网络连接
    # 设置模拟响应延迟 5 秒
    HTTPretty.register_uri(
        HTTPretty.GET,
        DELAYED_API_URL,
        body='{"key": "value"}',
        content_type="application/json",
        status=200,
        adding_headers={"X-Delay": "5"},
    )
    # 调用实际请求函数(假设已实现),并设置超时时间为 3 秒
    start_time = time.time()
    try:
        response = make_api_request(timeout=3)
    except requests.exceptions.Timeout:
        elapsed_time = time.time() - start_time
        assert elapsed_time >= 3  # 确保超时触发
        return  # 跳过后续断言,因为预期会抛出异常
    assert False, "Expected a Timeout exception, but it was not raised."

Example 5: Mocking paginated API responses

import json
from httpretty import HTTPretty, httprettified
# 分页查询 API 地址
PAGINATION_API_URL = "https://api.example.com/items"

@httprettified
def test_pagination_logic():
    # 预设第一页响应
    first_page_response = {
        "items": [{"id": 1, "name": "Item 1"}, {"id": 2, "name": "Item 2"}],
        "next_page": "https://api.example.com/items?page=2",
    }
    HTTPretty.register_uri(
        HTTPretty.GET,
        PAGINATION_API_URL,
        body=json.dumps(first_page_response),
        status=200,
        content_type="application/json",
    )
    # 预设第二页响应
    second_page_response = {
        "items": [{"id": 3, "name": "Item 3"}, {"id": 4, "name": "Item 4"}],
        "next_page": None,
    }
    HTTPretty.register_uri(
        HTTPretty.GET,
        first_page_response["next_page"],
        body=json.dumps(second_page_response),
        status=200,
        content_type="application/json",
    )
    # 调用实际分页查询函数(假设已实现)
    all_items = fetch_all_items(PAGINATION_API_URL)
    # 验证所有项目是否按预期顺序加载
    expected_items = [
        {"id": 1, "name": "Item 1"},
        {"id": 2, "name": "Item 2"},
        {"id": 3, "name": "Item 3"},
        {"id": 4, "name": "Item 4"},
    ]
    assert all_items == expected_items

These five examples show how to use HTTPretty in various scenarios—retrieving a WeChat access token, handling a subscription webhook, simulating a 404 error, testing timeout handling with delayed responses, and mocking paginated API responses—helping developers improve test efficiency and code quality.

pythonAPIMock ServerHTTP MockingHTTPretty
Test Development Learning Exchange
Written by

Test Development Learning Exchange

Test Development Learning Exchange

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.