Repository: getsentry/responses

Issue:
Integer request query parameters fail to match
### Steps to Reproduce

1. implement a test with `matchers.query_param_matcher` using integers
```python
@responses.activate
def test_bad_matcher():
    expected_query_params = {"number": 5}
    responses.add(
        responses.GET,
        "/fake",
        match=[matchers.query_param_matcher(expected_query_params)]
    )
    requests.get("/fake", params=expected_query_params)
```
### Expected Result

I would expect this test to pass.

### Actual Result

Instead, an extremely confusing failure is produced:

> Parameters do not match. {number: 5} doesn't match {number: 5}

The issue can be worked around by manually casting the integers to a string, but it would be great if the library were able to handle equivalent query params on its own.


Discussion:
codecov[bot]: # [Codecov](https://app.codecov.io/gh/getsentry/responses/compare/485?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getsentry) Report
> Merging [#485](https://app.codecov.io/gh/getsentry/responses/compare/485?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getsentry) (10f26ab) into [master](https://codecov.io/gh/getsentry/responses/commit/ee46f922e4271b583c5415ae29d77f563a66e751?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getsentry) (ee46f92) will **not change** coverage.
> The diff coverage is `100.00%`.

[![Impacted file tree graph](https://codecov.io/gh/getsentry/responses/pull/485/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/485?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getsentry)

```diff
@@            Coverage Diff            @@
##            master      #485   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files            6         6           
  Lines         2067      2078   +11     
=========================================
+ Hits          2067      2078   +11     
```


| [Impacted Files](https://app.codecov.io/gh/getsentry/responses/compare/485?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getsentry) | Coverage Δ | |
|---|---|---|
| [responses/matchers.py](https://app.codecov.io/gh/getsentry/responses/compare/485/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getsentry#diff-cmVzcG9uc2VzL21hdGNoZXJzLnB5) | `100.00% <100.00%> (ø)` | |
| [responses/test\_matchers.py](https://app.codecov.io/gh/getsentry/responses/compare/485/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getsentry#diff-cmVzcG9uc2VzL3Rlc3RfbWF0Y2hlcnMucHk=) | `100.00% <100.00%> (ø)` | |

------

[Continue to review full report at Codecov](https://app.codecov.io/gh/getsentry/responses/compare/485?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/485?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getsentry). Last update [ee46f92...10f26ab](https://app.codecov.io/gh/getsentry/responses/compare/485?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).


Patch:
diff --git a/CHANGES b/CHANGES
index 66c1659..8a4d3df 100644
--- a/CHANGES
+++ b/CHANGES
@@ -2,6 +2,7 @@
 ------
 
 * Expose `get_registry()` method of `RequestsMock` object. Replaces internal `_get_registry()`.
+* `query_param_matcher` can now accept dictionaries with `int` and `float` values.
 * Added support for `async/await` functions.
 
 0.18.0
diff --git a/responses/matchers.py b/responses/matchers.py
index 893edc1..1fee6a5 100644
--- a/responses/matchers.py
+++ b/responses/matchers.py
@@ -132,6 +132,10 @@ def query_param_matcher(params):
     :return: (func) matcher
     """
 
+    for k, v in params.items():
+        if isinstance(v, (int, float)):
+            params[k] = str(v)
+
     def match(request):
         reason = ""
         request_params = request.params
diff --git a/responses/matchers.pyi b/responses/matchers.pyi
index 188de2e..408eb55 100644
--- a/responses/matchers.pyi
+++ b/responses/matchers.pyi
@@ -19,7 +19,7 @@ def urlencoded_params_matcher(
 ) -> Callable[..., Any]: ...
 
 def query_param_matcher(
-    params: Optional[Dict[str, str]]
+    params: Optional[Dict[str, Any]]
 ) -> Callable[..., Any]: ...
 
 def query_string_matcher(


Test patch:
diff --git a/responses/test_matchers.py b/responses/test_matchers.py
index d061d97..937e8c0 100644
--- a/responses/test_matchers.py
+++ b/responses/test_matchers.py
@@ -87,6 +87,23 @@ def test_request_matches_post_params():
     assert_reset()
 
 
+def test_query_params_numbers():
+    @responses.activate
+    def run():
+        expected_query_params = {"float": 5.0, "int": 2}
+        responses.add(
+            responses.GET,
+            "https://example.com/",
+            match=[
+                matchers.query_param_matcher(expected_query_params),
+            ],
+        )
+        requests.get("https://example.com", params=expected_query_params)
+
+    run()
+    assert_reset()
+
+
 def test_request_matches_empty_body():
     def run():
         with responses.RequestsMock(assert_all_requests_are_fired=True) as rsps: