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

Comments:

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()