Repository: getsentry/responses

Issue:
Requesting a URL, then changing the response will return the old response
The documentation states:
> You can also add multiple responses for the same url: ....

However, this is not true if you interleave adding and requesting responses:
```py
>>> import responses
>>> import requests
>>> 
>>> responses.start()
>>> 
>>> responses.add(responses.GET, "https://example.com/",
...     json={'response': 'old'}
... )
>>> requests.get('https://example.com/').content
b'{"response": "old"}'
>>> 
>>> responses.add(responses.GET, "https://example.com/",
...     json={'response': 'new'}
... )
>>> 
>>> 
>>> requests.get('https://example.com/').content
b'{"response": "old"}'
>>> requests.get('https://example.com/').content
b'{"response": "new"}'
>>> requests.get('https://example.com/').content
b'{"response": "new"}'
```

Expected result: After adding the "new" response, a "new" response is returned in the subsequent request.

Requests version: '2.19.1', Python 3.6.6

Discussion:
codecov[bot]: # [Codecov](https://app.codecov.io/gh/getsentry/responses/compare/455?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getsentry) Report
> Merging [#455](https://app.codecov.io/gh/getsentry/responses/compare/455?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getsentry) (c6bde2e) into [master](https://codecov.io/gh/getsentry/responses/commit/5799ff68ebc00a2d0faa605136862614cf3a2f88?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getsentry) (5799ff6) will **increase** coverage by `0.00%`.
> The diff coverage is `100.00%`.

[![Impacted file tree graph](https://codecov.io/gh/getsentry/responses/pull/455/graphs/tree.svg?width=650&height=150&src=pr&token=x2tAGR7rxE&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getsentry)](https://app.codecov.io/gh/getsentry/responses/compare/455?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getsentry)

```diff
@@           Coverage Diff           @@
##           master     #455   +/-   ##
=======================================
  Coverage   99.79%   99.80%           
=======================================
  Files           4        4           
  Lines        1963     2002   +39     
=======================================
+ Hits         1959     1998   +39     
  Misses          4        4           
```


| [Impacted Files](https://app.codecov.io/gh/getsentry/responses/compare/455?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getsentry) | Coverage Δ | |
|---|---|---|
| [responses/\_\_init\_\_.py](https://app.codecov.io/gh/getsentry/responses/compare/455/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getsentry#diff-cmVzcG9uc2VzL19faW5pdF9fLnB5) | `100.00% <100.00%> (ø)` | |
| [responses/test\_responses.py](https://app.codecov.io/gh/getsentry/responses/compare/455/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getsentry#diff-cmVzcG9uc2VzL3Rlc3RfcmVzcG9uc2VzLnB5) | `99.65% <100.00%> (+0.01%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://app.codecov.io/gh/getsentry/responses/compare/455?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getsentry).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getsentry)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://app.codecov.io/gh/getsentry/responses/compare/455?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getsentry). Last update [5799ff6...c6bde2e](https://app.codecov.io/gh/getsentry/responses/compare/455?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getsentry). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getsentry).

beliaev-maksim: @markstory 
I would prefer merging current PR after #416 due to potential merge conflicts

Patch:
diff --git a/CHANGES b/CHANGES
index a90606b..200fc1b 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,17 +1,19 @@
 0.17.0
 ------
 
-* This release is the last one to support Python 2.7.
+* This release is the last to support Python 2.7.
 * Fixed issue when `response.iter_content` when `chunk_size=None` entered infinite loop
 * Fixed issue when `passthru_prefixes` persisted across tests.
   Now `add_passthru` is valid only within a context manager or for a single function and
   cleared on exit
-* Deprecate ``match_querystring`` argument in ``Response`` and ``CallbackResponse``.
+* Deprecate `match_querystring` argument in `Response`` and `CallbackResponse`.
   Use `responses.matchers.query_param_matcher` or `responses.matchers.query_string_matcher`
 * Added support for non-UTF-8 bytes in `responses.matchers.multipart_matcher`
 * Added `responses.registries`. Now user can create custom registries to
   manipulate the order of responses in the match algorithm
   `responses.activate(registry=CustomRegistry)`
+* Fixed issue with response match when requests were performed between adding responses with
+  same URL. See Issue #212
 
 0.16.0
 ------
diff --git a/responses/registries.py b/responses/registries.py
index 6546798..1e0f8c5 100644
--- a/responses/registries.py
+++ b/responses/registries.py
@@ -20,6 +20,11 @@ class FirstMatchRegistry(object):
                     found = i
                     found_match = response
                 else:
+                    if self.registered[found].call_count > 0:
+                        # that assumes that some responses were added between calls
+                        self.registered.pop(found)
+                        found_match = response
+                        break
                     # Multiple matches found.  Remove & return the first response.
                     return self.registered.pop(found), match_failed_reasons
             else:


Test patch:
diff --git a/responses/test_responses.py b/responses/test_responses.py
index e076ec7..92dfb43 100644
--- a/responses/test_responses.py
+++ b/responses/test_responses.py
@@ -1405,15 +1405,48 @@ def test_multiple_responses():
     def run():
         responses.add(responses.GET, "http://example.com", body="test")
         responses.add(responses.GET, "http://example.com", body="rest")
+        responses.add(responses.GET, "http://example.com", body="fest")
+        responses.add(responses.GET, "http://example.com", body="best")
 
         resp = requests.get("http://example.com")
         assert_response(resp, "test")
+
         resp = requests.get("http://example.com")
         assert_response(resp, "rest")
+
+        resp = requests.get("http://example.com")
+        assert_response(resp, "fest")
+
+        resp = requests.get("http://example.com")
+        assert_response(resp, "best")
+
         # After all responses are used, last response should be repeated
         resp = requests.get("http://example.com")
+        assert_response(resp, "best")
+
+    run()
+    assert_reset()
+
+
+def test_multiple_responses_intermixed():
+    @responses.activate
+    def run():
+        responses.add(responses.GET, "http://example.com", body="test")
+        resp = requests.get("http://example.com")
+        assert_response(resp, "test")
+
+        responses.add(responses.GET, "http://example.com", body="rest")
+        resp = requests.get("http://example.com")
         assert_response(resp, "rest")
 
+        responses.add(responses.GET, "http://example.com", body="best")
+        resp = requests.get("http://example.com")
+        assert_response(resp, "best")
+
+        # After all responses are used, last response should be repeated
+        resp = requests.get("http://example.com")
+        assert_response(resp, "best")
+
     run()
     assert_reset()
 
@@ -1916,3 +1949,21 @@ def test_registry_reset():
 
     run()
     assert_reset()
+
+
+def test_requests_between_add():
+    @responses.activate
+    def run():
+        responses.add(responses.GET, "https://example.com/", json={"response": "old"})
+        assert requests.get("https://example.com/").content == b'{"response": "old"}'
+        assert requests.get("https://example.com/").content == b'{"response": "old"}'
+        assert requests.get("https://example.com/").content == b'{"response": "old"}'
+
+        responses.add(responses.GET, "https://example.com/", json={"response": "new"})
+
+        assert requests.get("https://example.com/").content == b'{"response": "new"}'
+        assert requests.get("https://example.com/").content == b'{"response": "new"}'
+        assert requests.get("https://example.com/").content == b'{"response": "new"}'
+
+    run()
+    assert_reset()