Repository: pnuckowski/aioresponses

Issue:
mocking ignores base_url
`aiohttp.ClientSession` takes a `base_url` (https://docs.aiohttp.org/en/stable/client_reference.html?highlight=base_url#aiohttp.ClientSession) that is then used to build the URL with `.request()` and other methods. 

Sample usage:

```
In [3]: session = aiohttp.ClientSession("http://httpbin.org/")

In [4]: await session.get("/get")
Out[4]: 
<ClientResponse(http://httpbin.org/get) [200 OK]>
[…]
```

Unfortunately, `aioresponses` ignores that, so it's not possible to mock the full URL, because aioresponses would only pass `/get` to its matchers.

Discussion:

Patch:
diff --git a/aioresponses/core.py b/aioresponses/core.py
index a22fad6..425dff0 100644
--- a/aioresponses/core.py
+++ b/aioresponses/core.py
@@ -212,6 +212,9 @@ class RequestMatch(object):
             reason=result.reason)
         return resp
 
+    def __repr__(self) -> str:
+        return f"RequestMatch('{self.url_or_pattern}')"
+
 
 RequestCall = namedtuple('RequestCall', ['args', 'kwargs'])
 
@@ -496,7 +499,14 @@ class aioresponses(object):
         if orig_self.closed:
             raise RuntimeError('Session is closed')
 
-        url_origin = url
+        # Join url with ClientSession._base_url
+        url = orig_self._build_url(url)
+        url_origin = str(url)
+
+        # Combine ClientSession headers with passed headers
+        if orig_self.headers:
+            kwargs["headers"] = orig_self._prepare_headers(kwargs.get("headers"))
+
         url = normalize_url(merge_params(url, kwargs.get('params')))
         url_str = str(url)
         for prefix in self._passthrough:
diff --git a/requirements-dev.txt b/requirements-dev.txt
index f19c759..bb31c52 100644
--- a/requirements-dev.txt
+++ b/requirements-dev.txt
@@ -10,4 +10,5 @@ pytest-html==2.1.1
 ddt==1.4.1
 typing
 asynctest==0.13.0
-yarl==1.8.2
+yarl==1.9.4
+setuptools==69.5.1


Test patch:
diff --git a/tests/test_aioresponses.py b/tests/test_aioresponses.py
index 22b1bc4..38f6d99 100644
--- a/tests/test_aioresponses.py
+++ b/tests/test_aioresponses.py
@@ -10,7 +10,7 @@ from aiohttp import hdrs
 from aiohttp import http
 from aiohttp.client import ClientSession
 from aiohttp.client_reqrep import ClientResponse
-from ddt import ddt, data
+from ddt import ddt, data, unpack
 from packaging.version import Version
 
 try:
@@ -80,6 +80,31 @@ class AIOResponsesTestCase(AsyncTestCase):
         self.assertIsInstance(response, ClientResponse)
         self.assertEqual(response.status, 204)
 
+    @unpack
+    @data(
+        ("http://example.com", "/api?foo=bar#fragment"),
+        ("http://example.com/", "/api?foo=bar#fragment")
+    )
+    @aioresponses()
+    async def test_base_url(self, m, base_url, relative_url):
+        m.get(self.url, status=200)
+        self.session = ClientSession(base_url=base_url)
+        response = await self.session.get(relative_url)
+        self.assertEqual(response.status, 200)
+
+    @aioresponses()
+    async def test_session_headers(self, m):
+        m.get(self.url)
+        self.session = ClientSession(headers={"Authorization": "Bearer foobar"})
+        response = await self.session.get(self.url)
+
+        self.assertEqual(response.status, 200)
+
+        # Check that the headers from the ClientSession are within the request
+        key = ('GET', URL(self.url))
+        request = m.requests[key][0]
+        self.assertEqual(request.kwargs["headers"]["Authorization"], 'Bearer foobar')
+
     @aioresponses()
     async def test_returned_response_headers(self, m):
         m.get(self.url,