getsentry / responses

A utility for mocking out the Python Requests library.
Apache License 2.0
4.14k stars 354 forks source link

post method doesn't seem to follow retry mechanism #628

Closed obarbier closed 1 year ago

obarbier commented 1 year ago

Describe the bug

i have the following code which is causing test fail

    @responses.activate(registry=registries.OrderedRegistry)
    def test_basic(self):
        import requests
        url = "http://httpstat.us/412"
        rsp1 = responses.post(url, json="Error", status=500)
        rsp2 = responses.post(url, json="Error", status=500)
        rsp3 = responses.post(url, json="Error", status=500)
        rsp4 = responses.post(url, json="Error", status=500)
        rsp5 = responses.post(url, json="Error", status=500)
        t = [rsp1, rsp2, rsp3, rsp4, rsp5]
        responses.add(*t)
        adapter = HTTPAdapter(
            max_retries=Retry(
                total=_RETRY_LOGIC_COUNT,
                backoff_factor=0.1,
                status_forcelist=[412, 500, 502, 503],
                raise_on_status=False,
            )
        )
        session = requests.Session()
        session.mount("http://", adapter)
        r = session.post(url)
        print(r.status_code, r.text)
        assert rsp1.call_count == 1
        assert rsp2.call_count == 1
        assert rsp3.call_count == 1
        assert rsp4.call_count == 1
        assert rsp5.call_count == 1

However the same test pass when using get request

    @responses.activate(registry=registries.OrderedRegistry)
    def test_basic(self):
        import requests
        url = "http://httpstat.us/412"
        rsp1 = responses.get(url, json="Error", status=500)
        rsp2 = responses.get(url, json="Error", status=500)
        rsp3 = responses.get(url, json="Error", status=500)
        rsp4 = responses.get(url, json="Error", status=500)
        rsp5 = responses.get(url, json="Error", status=500)
        t = [rsp1, rsp2, rsp3, rsp4, rsp5]
        responses.add(*t)
        adapter = HTTPAdapter(
            max_retries=Retry(
                total=_RETRY_LOGIC_COUNT,
                backoff_factor=0.1,
                status_forcelist=[412, 500, 502, 503],
                raise_on_status=False,
            )
        )
        session = requests.Session()
        session.mount("http://", adapter)
        r = session.get(url)
        print(r.status_code, r.text)
        assert rsp1.call_count == 1
        assert rsp2.call_count == 1
        assert rsp3.call_count == 1
        assert rsp4.call_count == 1
        assert rsp5.call_count == 1

Additional context

No response

Version of responses

0.20.0

Steps to Reproduce

    @responses.activate(registry=registries.OrderedRegistry)
    def test_basic(self):
        import requests
        url = "http://httpstat.us/412"
        rsp1 = responses.post(url, json="Error", status=500)
        rsp2 = responses.post(url, json="Error", status=500)
        rsp3 = responses.post(url, json="Error", status=500)
        rsp4 = responses.post(url, json="Error", status=500)
        rsp5 = responses.post(url, json="Error", status=500)
        t = [rsp1, rsp2, rsp3, rsp4, rsp5]
        responses.add(*t)
        adapter = HTTPAdapter(
            max_retries=Retry(
                total=_RETRY_LOGIC_COUNT,
                backoff_factor=0.1,
                status_forcelist=[412, 500, 502, 503],
                raise_on_status=False,
            )
        )
        session = requests.Session()
        session.mount("http://", adapter)
        r = session.post(url)
        print(r.status_code, r.text)
        assert rsp1.call_count == 1
        assert rsp2.call_count == 1
        assert rsp3.call_count == 1
        assert rsp4.call_count == 1
        assert rsp5.call_count == 1

Expected Result

the test should pass

Actual Result

Failure Traceback (most recent call last): File "", line 218, in wrapper return func(*args, **kwargs) File "", line 118, in test_basic assert rsp2.call_count == 1 AssertionError

beliaev-maksim commented 1 year ago

hello @obarbier

first of all your example is not a minimal reproducible. Try to copy and paste, then run. It will not

second, Retry, does not work by default with POST

:param iterable allowed_methods:
        Set of uppercased HTTP method verbs that we should retry on.

        By default, we only retry on methods which are considered to be
        idempotent (multiple requests with the same parameters end with the
        same state). See :attr:`Retry.DEFAULT_ALLOWED_METHODS`.

        Set to a ``False`` value to retry on any verb.

        .. warning::

            Previously this parameter was named ``method_whitelist``, that
            usage is deprecated in v1.26.0 and will be removed in v2.0.
DEFAULT_ALLOWED_METHODS = frozenset(
        ["HEAD", "GET", "PUT", "DELETE", "OPTIONS", "TRACE"]
    )
obarbier commented 1 year ago

@beliaev-maksim thank you that was a great insight