Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor tests to use MockTransport(<handler_function>) #1281

Merged
merged 11 commits into from
Sep 12, 2020

Conversation

tomchristie
Copy link
Member

@tomchristie tomchristie commented Sep 11, 2020

Refactors our test cases so that we're able to test against simple request/response handler functions.

import httpx
from tests.utils import MockTransport

def app(request: httpx.Request) -> httpx.Response:
    ...

def test_something():
    client = httpx.Client(transport=MockTransport(app))
    response = client.get(...)

This is actually kind of a big deal. 🤗

Everything is still passing through our really tightly defined transport API, but we get the benefits of being able to work with proper request/response instances, rather than having to build out test behaviours by scratching around with bytewise variables, raw header lists, and httpcore.SyncIteratorStream/httpcore.AsyncIteratorStream instances.

Still need to clean up client/test_auth.py using this, but have covered all the other client test modules.

The implementation of MockTransport in the tests/utils.py module also gives us a really good concrete case to work against for working through some of the more nitty gritty details of the request/response APIs.

Really we'd like for the implementation to be as simple as...

class MockTransport(httpcore.SyncHTTPTransport):
    def __init__(self, handler: Callable) -> None:
        self.handler = handler

    def request(
        self,
        method: bytes,
        url: Tuple[bytes, bytes, Optional[int], bytes],
        headers: List[Tuple[bytes, bytes]] = None,
        stream: httpcore.SyncByteStream = None,
        timeout: Mapping[str, Optional[float]] = None,
    ) -> Tuple[bytes, int, bytes, List[Tuple[bytes, bytes]], httpcore.SyncByteStream]:
        request = httpx.Request(method=method, url=url, headers=headers, content=stream)
        request.read()
        response = self.handler(request)
        return (
            response.http_version.encode("ascii"),
            response.status_code,
            response.reason_phrase.encode("ascii"),
            response.headers.raw,
            response.stream
        )

(In fact in addition to that, we'd probably also like to end up with an API that allows MockTransport be usable with either sync or async clients, rather than having to have separate MockTransport and AsyncMockTransport classes, but let's save that conversation for another day.)

The existing implementation here gives us something to work against, while tackling little parts of that incrementally. Eg. adding support for passing raw URL tuples of (<bytes>, <bytes>, <optional int>, <bytes>) to httpx.URL(...), and also some of the details around #1253

Related to #1091

@tomchristie tomchristie added the refactor Issues and PRs related to code refactoring label Sep 11, 2020
and (
"Content-Length" in request_headers
or "Transfer-Encoding" in request_headers
)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a bit fiddly to explain why we're having to do this at the moment, but it's related to some of the grungy bits that need ironing out in #1253.

I'll resolve it as part of a follow-up.

Copy link
Member

@florimondmanca florimondmanca left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice indeed! 💯 👍

@tomchristie tomchristie merged commit c2afd2d into master Sep 12, 2020
@tomchristie tomchristie deleted the mock-transport branch September 12, 2020 10:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
refactor Issues and PRs related to code refactoring
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants