Skip to content

Allow usage with httpx.MockTransport #167

@CarliJoy

Description

@CarliJoy

In certain use cases, pytest_httpx is used only to mock a single httpx client, specifically one responsible for connecting to a cluster of servers for service A. However, while mocking this specific client, we still want the flexibility to make normal, non-mocked requests to other services without impacting the entire environment.

Previously, we initialized HTTPXMock directly, but with recent changes, this is no longer supported. While the focus on clean interfaces is understandable, this change limits the ability to easily create single mocked clients while keeping other requests unaltered.

To address this, I propose adding support for a MockTransport, as outlined below:

TCallable = TypeVar("TCallable", bound=Callable)

def copy_docs(source_func: Callable) -> Callable[[TCallable], TCallable]:
    def apply_docs(target_func: TCallable) -> TCallable:
        target_func.__doc__ == source_func.__doc__

class MockedTransport(httpx.MockTransport):
    def __init__(
        self,
        assert_all_responses_were_requested: bool = True,
        assert_all_requests_were_expected: bool = True,
        can_send_already_matched_responses: bool = False,
    ):
        _pool = None  # enusre _proxy_url does not fail
        options = _HTTPXMockOptions(
            can_send_already_matched_responses=can_send_already_matched_responses,
            assert_all_responses_were_requested=assert_all_responses_were_requested,
            assert_all_requests_were_expected=assert_all_requests_were_expected,
        )
        self.mock = HTTPXMock(options)
        super().__init__(lambda request: self.mock._handle_request(self, request))

    # TODO copy call signature
    # see https://stackoverflow.com/a/71968448/3813064 or
    #     https://github.com/python/cpython/pull/121693
    @copy_docs(HTTPXMock.add_response)
    def add_response(self, *args, **kwargs) -> None:
        self.mock.add_response(*args, **kwargs)

    @copy_docs(HTTPXMock.add_callback)
    def add_callback(self, *args, **kwargs) -> None:
        self.mock.add_callback(*args, **kwargs)

    @copy_docs(HTTPXMock.add_exception)
    def add_exception(self, *args, **kwargs) -> None:
        self.mock.add_exception(*args, **kwargs)

The MockedTransport class extends integrate smoothly with HTTPXMock, allowing targeted client mocking while enabling other clients to make live requests as usual.

Metadata

Metadata

Assignees

No one assigned

    Labels

    questionFurther information is requested

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions