From 1b6f304421e6aef6a56c980ae69d5fd5b3cbe578 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steinn=20Eldj=C3=A1rn=20Sigur=C3=B0arson?= Date: Tue, 4 Jun 2019 14:26:02 +0000 Subject: [PATCH 1/5] Add .content to MockClientResponse so code which uses aiohttp request content streams directly can be tested --- vcr/stubs/aiohttp_stubs/__init__.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/vcr/stubs/aiohttp_stubs/__init__.py b/vcr/stubs/aiohttp_stubs/__init__.py index f6525c7..8e03907 100644 --- a/vcr/stubs/aiohttp_stubs/__init__.py +++ b/vcr/stubs/aiohttp_stubs/__init__.py @@ -5,12 +5,16 @@ import asyncio import functools import json -from aiohttp import ClientResponse +from aiohttp import ClientResponse, streams from yarl import URL from vcr.request import Request +class MockStream(asyncio.StreamReader, streams.AsyncStreamReaderMixin): + pass + + class MockClientResponse(ClientResponse): def __init__(self, method, url): super().__init__( @@ -37,6 +41,13 @@ class MockClientResponse(ClientResponse): def release(self): pass + @property + def content(self): + s = MockStream() + s.feed_data(self._body) + s.feed_eof() + return s + def vcr_request(cassette, real_request): @functools.wraps(real_request) From cc55ef5b357af58a7803b86dec87dbe69b0ff6db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steinn=20Eldj=C3=A1rn=20Sigur=C3=B0arson?= Date: Tue, 4 Jun 2019 14:27:13 +0000 Subject: [PATCH 2/5] Add test for MockStream on aiohttp --- tests/integration/test_aiohttp.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/integration/test_aiohttp.py b/tests/integration/test_aiohttp.py index c20dc61..c2145af 100644 --- a/tests/integration/test_aiohttp.py +++ b/tests/integration/test_aiohttp.py @@ -93,6 +93,24 @@ def test_binary(tmpdir, scheme): assert cassette.play_count == 1 +@pytest.mark.asyncio +async def test_stream(tmpdir, scheme): + url = scheme + '://httpbin.org/get' + headers = {'Content-Type': 'application/json'} + + with vcr.use_cassette(str(tmpdir.join('stream.yaml'))): + async with aiohttp.ClientSession() as session: + resp = await session.get(url, headers=headers) + body = await resp.read() # do not use stream interface here, the stream seems exhausted by vcr + + with vcr.use_cassette(str(tmpdir.join('stream.yaml'))) as cassette: + async with aiohttp.ClientSession() as session: + cassette_resp = await session.get(url, headers=headers) + cassette_body = await cassette_resp.content.read() + assert cassette_body == body + assert cassette.play_count == 1 + + def test_post(tmpdir, scheme): data = {'key1': 'value1', 'key2': 'value2'} url = scheme + '://httpbin.org/post' From 6c41b8b723497f8736bf1b96003d650ee5feb078 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steinn=20Eldj=C3=A1rn=20Sigur=C3=B0arson?= Date: Fri, 28 Jun 2019 13:30:14 +0000 Subject: [PATCH 3/5] Use built-in helpers to avoid use of async keywords which cause syntax errors on 2.x --- tests/integration/test_aiohttp.py | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/tests/integration/test_aiohttp.py b/tests/integration/test_aiohttp.py index c2145af..58b9a62 100644 --- a/tests/integration/test_aiohttp.py +++ b/tests/integration/test_aiohttp.py @@ -93,20 +93,15 @@ def test_binary(tmpdir, scheme): assert cassette.play_count == 1 -@pytest.mark.asyncio -async def test_stream(tmpdir, scheme): +def test_stream(tmpdir, scheme): url = scheme + '://httpbin.org/get' headers = {'Content-Type': 'application/json'} with vcr.use_cassette(str(tmpdir.join('stream.yaml'))): - async with aiohttp.ClientSession() as session: - resp = await session.get(url, headers=headers) - body = await resp.read() # do not use stream interface here, the stream seems exhausted by vcr + resp, body = get(url, output='raw') # XXX: headers? with vcr.use_cassette(str(tmpdir.join('stream.yaml'))) as cassette: - async with aiohttp.ClientSession() as session: - cassette_resp = await session.get(url, headers=headers) - cassette_body = await cassette_resp.content.read() + cassette_resp, cassette_body = get(url, output='raw') assert cassette_body == body assert cassette.play_count == 1 From 67b03b45c338143d0e1496dc0c48046ca000b8e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steinn=20Eldj=C3=A1rn=20Sigur=C3=B0arson?= Date: Fri, 28 Jun 2019 13:34:48 +0000 Subject: [PATCH 4/5] Add output option to use response.content stream --- tests/integration/aiohttp_utils.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/integration/aiohttp_utils.py b/tests/integration/aiohttp_utils.py index 6f6f15e..c8c1b0b 100644 --- a/tests/integration/aiohttp_utils.py +++ b/tests/integration/aiohttp_utils.py @@ -17,6 +17,8 @@ async def aiohttp_request(loop, method, url, output='text', encoding='utf-8', co content = await response.json(encoding=encoding, content_type=content_type) elif output == 'raw': content = await response.read() + elif output == 'stream': + content = await response.content.read() response_ctx._resp.close() await session.close() From e8a9a65befd4c99634da369628da5104ff27b36d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steinn=20Eldj=C3=A1rn=20Sigur=C3=B0arson?= Date: Fri, 28 Jun 2019 13:35:05 +0000 Subject: [PATCH 5/5] Make test use stream output to test MockStream interface --- tests/integration/test_aiohttp.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/integration/test_aiohttp.py b/tests/integration/test_aiohttp.py index 58b9a62..a02c982 100644 --- a/tests/integration/test_aiohttp.py +++ b/tests/integration/test_aiohttp.py @@ -95,13 +95,12 @@ def test_binary(tmpdir, scheme): def test_stream(tmpdir, scheme): url = scheme + '://httpbin.org/get' - headers = {'Content-Type': 'application/json'} with vcr.use_cassette(str(tmpdir.join('stream.yaml'))): - resp, body = get(url, output='raw') # XXX: headers? + resp, body = get(url, output='raw') # Do not use stream here, as the stream is exhausted by vcr with vcr.use_cassette(str(tmpdir.join('stream.yaml'))) as cassette: - cassette_resp, cassette_body = get(url, output='raw') + cassette_resp, cassette_body = get(url, output='stream') assert cassette_body == body assert cassette.play_count == 1