Metadata-Version: 2.1
Name: respx
Version: 0.7.2
Summary: A utility for mocking out the Python HTTPX library.
Home-page: https://github.com/lundberg/respx
Author: Jonas Lundberg
Author-email: jonas@5monkeys.se
License: MIT
Description: # RESPX
        
        ![](https://github.com/lundberg/respx/workflows/test/badge.svg)
        [![codecov](https://codecov.io/gh/lundberg/respx/branch/master/graph/badge.svg)](https://codecov.io/gh/lundberg/respx)
        [![PyPi Version](https://img.shields.io/pypi/v/respx.svg)](https://pypi.org/project/respx/)
        [![Python Versions](https://img.shields.io/pypi/pyversions/respx.svg)](https://pypi.org/project/respx/)
        
        A utility for mocking out the Python [HTTPX](https://github.com/encode/httpx) library.
        
        ## Usage
        
        For starters, you need to mock `HTTPX`, by using the `RESPX` **decorator** or **context managers**.
        
        
        ## Decorator
        
        ```py
        import httpx
        import respx
        
        
        @respx.mock
        def test_something():
            request = respx.post("https://foo.bar/baz/", status_code=201)
            response = httpx.post("https://foo.bar/baz/")
            assert request.called
            assert response.status_code == 201
        ```
        
        
        ## Context Manager
        
        Using the high-level api:
        
        ```py
        import httpx
        import respx
        
        
        with respx.mock():
            request = respx.get("https://foo.bar/", content={"foo": "bar"})
            response = httpx.get("https://foo.bar/")
            assert request.called
            assert response.json() == {"foo": "bar"}
        ```
        
        Using the low-level api:
        
        ```py
        import httpx
        import respx
        
        
        with respx.HTTPXMock() as respx_mock:
            request = respx_mock.get("https://foo.bar/", content={"foo": "bar"})
            response = httpx.get("https://foo.bar/")
            assert request.called
            assert response.json() == {"foo": "bar"}
        ```
        
        > **NOTE:** You can also start and stop mocking `HTTPX` manually, by calling `respx.start()` and `respx.stop()`
        
        
        ## Mocking responses
        
        To mock a response, define the *request pattern* to match and the *response details* to return.
        
        For regular and simple use, use the HTTP method shorthands:
        
        **`respx.get`**(*url=None, status_code=None, content=None, content_type=None, headers=None, pass_through=False, alias=None*) -> RequestPattern
        
        **`respx.options`**(*url=None, ...*)
        
        **`respx.head`**(*url=None, ...*)
        
        **`respx.post`**(*url=None, ...*)
        
        **`respx.put`**(*url=None, ...*)
        
        **`respx.patch`**(*url=None, ...*)
        
        **`respx.delete`**(*url=None, ...*)
        
        For advanced use:
        
        **`respx.request`**(*method, url=None, status_code=None, content=None, content_type=None, headers=None, pass_through=False, alias=None*) -> RequestPattern
        
        ### Parameters
        
        > * **method** - *str | callable*  
        >   * Request HTTP method to match - GET, OPTIONS, HEAD, POST, PUT, PATCH or DELETE.
        >   * Request match callback. *See [Custom request matching](#custom-request-matching).*
        > * **url** - *(optional) str | pattern*  
        >   * Request URL exact string to match.
        >   * Request URL pattern to match. *See [URL pattern matching](#url-pattern-matching).*
        > * **status_code** - *(optional) int*  
        >   Response status code. [Default: 200]
        > * **content** - *(optional) bytes | str | list | dict | callable | exception*  
        >   Response content. [Default: b""] - *See [JSON content](#json-content), [Content callback](#content-callback).*
        > * **content_type** - *(optional) str*  
        >   Response Content-Type header value. [Default: text/plain]
        > * **headers** - *(optional) dict*  
        >   Response headers.
        > * **pass_through** - *(optional) bool*  
        >   Mark request to pass-through to real server, e.g. don't mock. [Default: False]
        > * **alias** - *(optional) str*  
        >   Name this request pattern. - *See [Call stats](#call-stats).*
        
        
        ## URL pattern matching
        
        Instead of matching an exact URL, you can pass a *compiled regex* to match the request URL.
        
        ```py
        import httpx
        import re
        import respx
        
        
        @respx.mock
        def test_something():
            respx.get(re.compile(r"^https://foo.bar/.*$"), content="Baz")
            response = httpx.get("https://foo.bar/baz/")
            assert response.text == "Baz"
        ```
        > **NOTE:** Named groups in the pattern will be passed as `kwargs` to [content callback](#content-callback), if used.
        
        
        ## JSON content
        
        To mock a response with json content, pass a `list` or `dict`. The `Content-Type` header will be set to `application/json`.
        
        ```py
        import httpx
        import respx
        
        
        @respx.mock
        def test_something():
            respx.get("https://foo.bar/baz/123/", content={"id": 123})
            response = httpx.get("https://foo.bar/baz/123/")
            assert response.json() == {"id": 123}
        ```
        
        ## Content callback
        
        If you need dynamic response content, use a callback function as the `content` parameter.
        
        ```py
        import httpx
        import re
        import respx
        
        
        def baz_content(request, pk=None):
            """
            If a URL pattern were used, named groups will be passed as optional kwargs.
            
            Return bytes, str, list or a dict.
            """
            return {"id": int(pk)}
        
        
        @respx.mock
        def test_something():
            respx.get(re.compile(r"^https://foo.bar/baz/(?P<pk>\d+)/$"), content=baz_content)
            response = httpx.get("https://foo.bar/baz/123/")
            assert response.json() == {"id": 123}
        ```
        
        
        ## Mock a request exception
        
        To simulate a request problem, *like a connection error*, pass an `Exception` instance as the `content` parameter.
        
        ```py
        import httpx
        import respx
        
        
        @respx.mock
        def test_something():
            respx.get("https://foo.bar/", content=httpx.ConnectTimeout())
            response = httpx.get("https://foo.bar/")  # Will raise
        ```
        
        
        ## Custom request matching
        
        For full control of what to *match* and what response to *mock*, pass a callback function as the `method` parameter.
        
        ```py
        import httpx
        import respx
        
        
        def custom_matcher(request, response):
            """
            Response object is populated with any given response parameters from the respx.request(...) call.
        
            Return None to not match.
            Return the response for a match and to mock this request.
            Return the request for pass-through behaviour.
            """
            if request.method != "POST":
                return None
                
            if "X-Auth-Token" not in request.headers:
                response.status_code = 401
            else:
                response.content = "OK"
                
            return response
        
        
        @respx.mock
        def test_something():
            custom_request = respx.request(custom_matcher, status_code=201)
            respx.get("https://foo.bar/baz/")
        
            response = httpx.get("https://foo.bar/baz/")
            assert response.status_code == 200
            assert not custom_request.called
        
            response = httpx.post("https://foo.bar/baz/")
            assert response.status_code == 401
            assert custom_request.called
            
            response = httpx.post("https://foo.bar/baz/", headers={"X-Auth-Token": "token"})
            assert response.status_code == 201
            assert custom_request.call_count == 2
        ```
        
        
        ## Repeated patterns
        
        If you mock several responses with the same request pattern, they will be matched in order, and popped til the last one.
        
        ```py
        import httpx
        import respx
        
        
        @respx.mock
        def test_something():
            respx.get("https://foo.bar/baz/123/", status_code=404)
            respx.get("https://foo.bar/baz/123/", content={"id": 123})
            respx.post("https://foo.bar/baz/", status_code=201)
        
            response = httpx.get("https://foo.bar/baz/123/")
            assert response.status_code == 404  # First match
        
            response = httpx.post("https://foo.bar/baz/")
            assert response.status_code == 201
        
            response = httpx.get("https://foo.bar/baz/123/")
            assert response.status_code == 200  # Second match
            assert response.json() == {"id": 123}
        ```
        
        
        ## Built-in assertions
        
        RESPX has the following build-in assertion checks:
        
        > * **assert_all_mocked**  
        >   Asserts that all captured `HTTPX` requests are mocked.
        > * **assert_all_called**  
        >   Asserts that all mocked request patterns were called.
        
        When using the high-level `respx.mock` decorator/manager, `assert_all_called` is **disabled**.  
        When using the low-level `respx.HTTPXMock` context manager, both checks is **enabled** by default.  
        
        ```py
        with respx.HTTPXMock(assert_all_called=False, assert_all_mocked=False) as respx_mock:
            response = httpx.get("https://foo.bar/")  # Will not raise AssersionError, but instead auto mock.
            assert response.status_code == 200
            assert respx_mock.stats.call_count == 1
        ```
        
        
        ## Call stats
        
        The global `respx` api has a `.calls` list, containing captured (`request`, `response`) tuples. On top of that there's also a *MagicMock* `.stats` object with all its bells and whistles, i.e. `call_count`, `assert_called_once` etc.
        
        Request patterns has their own `.calls` and `.stats`, along with shortcuts to stats`.called` and `.call_count`.
        
        ```py
        import httpx
        import respx
        
        
        @respx.mock
        def test_something():
            respx.get("https://foo.bar/", alias="index")  # Aliased request pattern
            create_request = respx.post("https://foo.bar/baz/")
            put_request = respx.put("https://foo.bar/baz/123/", status_code=202)
            
            httpx.get("https://foo.bar/")
            index_request = respx.aliases["index"]  # Alias
            assert index_request.called
            assert index_request.call_count == 1
        
            httpx.post("https://foo.bar/baz/")
            assert create_request.called
            assert create_request.call_count == 1
        
            httpx.put("https://foo.bar/baz/123/")
            assert put_request.called
            assert put_request.call_count == 1
            
            assert respx.stats.call_count == 3
            
            request, response = respx.calls[-1]
            assert request.method == "PUT"
            assert response.status_code == 202
        ```
        
Keywords: httpx,mock,responses,requests,async,http,client
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Description-Content-Type: text/markdown
