class ProxiedClientSession: """A ClientSession that forwards requests through a custom proxy.""" def __init__(self, *args: Any, **kwargs: Any) -> None: self.proxy_url = kwargs.pop("proxy_url") self.permanent_headers = { "Proxy-Authorization-Key": kwargs.pop("authorization"), "Accept": "application/json", } self._session = ClientSession(*args, **kwargs) def get(self, url: str, *args: Any, **kwargs: Any) -> _RequestContextManager: headers = kwargs.pop("headers", {}) headers.update(self.permanent_headers) headers["Requested-URI"] = url return self._session.get(self.proxy_url, headers=headers, *args, **kwargs) def post(self, url: str, *args: Any, **kwargs: Any) -> _RequestContextManager: headers = kwargs.pop("headers", {}) headers.update(self.permanent_headers) headers["Requested-URI"] = url return self._session.post(self.proxy_url, headers=headers, *args, **kwargs)
async def convert_html_to_pdf(session: ClientSession, url: str, data: bytes) -> None: """ Tests ability of server to serve its main and sole purpose: receive an html file and return its pdf version back :param session: session object of aiohttp :param url: address of the server which is being tested :param data: an html file as bytes :return: None """ async with session.post(url, data=data) as response: logger.debug(f'status code: {response.status}') if response.status == 200: async with aiofiles.open('file.pdf', 'wb') as file: while True: chunk = await response.content.read(1024) if not chunk: break await file.write(chunk) else: print(await response.text())
class AIOResponsesTestCase(TestCase): use_default_loop = False @asyncio.coroutine def setUp(self): self.url = 'http://example.com/api' self.session = ClientSession() super().setUp() @asyncio.coroutine def tearDown(self): self.session.close() super().tearDown() @data( hdrs.METH_HEAD, hdrs.METH_GET, hdrs.METH_POST, hdrs.METH_PUT, hdrs.METH_PATCH, hdrs.METH_DELETE, hdrs.METH_OPTIONS, ) @patch('aioresponses.aioresponses.add') @fail_on(unused_loop=False) def test_shortcut_method(self, http_method, mocked): with aioresponses() as m: getattr(m, http_method.lower())(self.url) mocked.assert_called_once_with(self.url, method=http_method) @aioresponses() def test_returned_instance(self, m): m.get(self.url) response = self.loop.run_until_complete(self.session.get(self.url)) self.assertIsInstance(response, ClientResponse) @aioresponses() @asyncio.coroutine def test_returned_instance_and_status_code(self, m): m.get(self.url, status=204) response = yield from self.session.get(self.url) self.assertIsInstance(response, ClientResponse) self.assertEqual(response.status, 204) @aioresponses() @asyncio.coroutine def test_returned_response_headers(self, m): m.get(self.url, content_type='text/html', headers={'Connection': 'keep-alive'}) response = yield from self.session.get(self.url) self.assertEqual(response.headers['Connection'], 'keep-alive') self.assertEqual(response.headers[hdrs.CONTENT_TYPE], 'text/html') @aioresponses() def test_method_dont_match(self, m): m.get(self.url) with self.assertRaises(ClientConnectionError): self.loop.run_until_complete(self.session.post(self.url)) @aioresponses() @asyncio.coroutine def test_streaming(self, m): m.get(self.url, body='Test') resp = yield from self.session.get(self.url) content = yield from resp.content.read() self.assertEqual(content, b'Test') @aioresponses() @asyncio.coroutine def test_streaming_up_to(self, m): m.get(self.url, body='Test') resp = yield from self.session.get(self.url) content = yield from resp.content.read(2) self.assertEqual(content, b'Te') content = yield from resp.content.read(2) self.assertEqual(content, b'st') @asyncio.coroutine def test_mocking_as_context_manager(self): with aioresponses() as aiomock: aiomock.add(self.url, payload={'foo': 'bar'}) resp = yield from self.session.get(self.url) self.assertEqual(resp.status, 200) payload = yield from resp.json() self.assertDictEqual(payload, {'foo': 'bar'}) def test_mocking_as_decorator(self): @aioresponses() def foo(loop, m): m.add(self.url, payload={'foo': 'bar'}) resp = loop.run_until_complete(self.session.get(self.url)) self.assertEqual(resp.status, 200) payload = loop.run_until_complete(resp.json()) self.assertDictEqual(payload, {'foo': 'bar'}) foo(self.loop) @asyncio.coroutine def test_passing_argument(self): @aioresponses(param='mocked') @asyncio.coroutine def foo(mocked): mocked.add(self.url, payload={'foo': 'bar'}) resp = yield from self.session.get(self.url) self.assertEqual(resp.status, 200) yield from foo() @fail_on(unused_loop=False) def test_mocking_as_decorator_wrong_mocked_arg_name(self): @aioresponses(param='foo') def foo(bar): # no matter what is here it should raise an error pass with self.assertRaises(TypeError) as cm: foo() exc = cm.exception self.assertIn("foo() got an unexpected keyword argument 'foo'", str(exc)) @asyncio.coroutine def test_unknown_request(self): with aioresponses() as aiomock: aiomock.add(self.url, payload={'foo': 'bar'}) with self.assertRaises(ClientConnectionError): yield from self.session.get('http://example.com/foo') @asyncio.coroutine def test_raising_custom_error(self): with aioresponses() as aiomock: aiomock.get(self.url, exception=HttpProcessingError(message='foo')) with self.assertRaises(HttpProcessingError): yield from self.session.get(self.url) @asyncio.coroutine def test_multiple_requests(self): with aioresponses() as m: m.get(self.url, status=200) m.get(self.url, status=201) m.get(self.url, status=202) resp = yield from self.session.get(self.url) self.assertEqual(resp.status, 200) resp = yield from self.session.get(self.url) self.assertEqual(resp.status, 201) resp = yield from self.session.get(self.url) self.assertEqual(resp.status, 202) key = ('GET', self.url) self.assertIn(key, m.requests) self.assertEqual(len(m.requests[key]), 3) self.assertEqual(m.requests[key][0].args, tuple()) self.assertEqual(m.requests[key][0].kwargs, {'allow_redirects': True}) @asyncio.coroutine def test_address_as_instance_of_url_combined_with_pass_through(self): external_api = 'http://httpbin.org/status/201' @asyncio.coroutine def doit(): api_resp = yield from self.session.get(self.url) # we have to hit actual url, # otherwise we do not test pass through option properly ext_rep = yield from self.session.get(URL(external_api)) return api_resp, ext_rep with aioresponses(passthrough=[external_api]) as m: m.get(self.url, status=200) api, ext = yield from doit() self.assertEqual(api.status, 200) self.assertEqual(ext.status, 201)
class AIOResponsesTestCase(AsyncTestCase): async def setup(self): self.url = 'http://example.com/api?foo=bar#fragment' self.session = ClientSession() async def teardown(self): close_result = self.session.close() if close_result is not None: await close_result def run_async(self, coroutine: Union[Coroutine, Generator]): return self.loop.run_until_complete(coroutine) async def request(self, url: str): return await self.session.get(url) @data( hdrs.METH_HEAD, hdrs.METH_GET, hdrs.METH_POST, hdrs.METH_PUT, hdrs.METH_PATCH, hdrs.METH_DELETE, hdrs.METH_OPTIONS, ) @patch('aioresponses.aioresponses.add') @fail_on(unused_loop=False) def test_shortcut_method(self, http_method, mocked): with aioresponses() as m: getattr(m, http_method.lower())(self.url) mocked.assert_called_once_with(self.url, method=http_method) @aioresponses() def test_returned_instance(self, m): m.get(self.url) response = self.run_async(self.session.get(self.url)) self.assertIsInstance(response, ClientResponse) @aioresponses() async def test_returned_instance_and_status_code(self, m): m.get(self.url, status=204) response = await self.session.get(self.url) self.assertIsInstance(response, ClientResponse) self.assertEqual(response.status, 204) @aioresponses() async def test_returned_response_headers(self, m): m.get(self.url, content_type='text/html', headers={'Connection': 'keep-alive'}) response = await self.session.get(self.url) self.assertEqual(response.headers['Connection'], 'keep-alive') self.assertEqual(response.headers[hdrs.CONTENT_TYPE], 'text/html') @aioresponses() async def test_returned_response_cookies(self, m): m.get(self.url, headers={'Set-Cookie': 'cookie=value'}) response = await self.session.get(self.url) self.assertEqual(response.cookies['cookie'].value, 'value') @aioresponses() async def test_returned_response_raw_headers(self, m): m.get(self.url, content_type='text/html', headers={'Connection': 'keep-alive'}) response = await self.session.get(self.url) expected_raw_headers = ((hdrs.CONTENT_TYPE.encode(), b'text/html'), (b'Connection', b'keep-alive')) self.assertEqual(response.raw_headers, expected_raw_headers) @aioresponses() async def test_raise_for_status(self, m): m.get(self.url, status=400) with self.assertRaises(ClientResponseError) as cm: response = await self.session.get(self.url) response.raise_for_status() self.assertEqual(cm.exception.message, http.RESPONSES[400][0]) @aioresponses() @skipIf(condition=AIOHTTP_VERSION < '3.4.0', reason='aiohttp<3.4.0 does not support raise_for_status ' 'arguments for requests') async def test_request_raise_for_status(self, m): m.get(self.url, status=400) with self.assertRaises(ClientResponseError) as cm: await self.session.get(self.url, raise_for_status=True) self.assertEqual(cm.exception.message, http.RESPONSES[400][0]) @aioresponses() async def test_returned_instance_and_params_handling(self, m): expected_url = 'http://example.com/api?foo=bar&x=42#fragment' m.get(expected_url) response = await self.session.get(self.url, params={'x': 42}) self.assertIsInstance(response, ClientResponse) self.assertEqual(response.status, 200) expected_url = 'http://example.com/api?x=42#fragment' m.get(expected_url) response = await self.session.get('http://example.com/api#fragment', params={'x': 42}) self.assertIsInstance(response, ClientResponse) self.assertEqual(response.status, 200) @aioresponses() def test_method_dont_match(self, m): m.get(self.url) with self.assertRaises(ClientConnectionError): self.run_async(self.session.post(self.url)) @aioresponses() async def test_streaming(self, m): m.get(self.url, body='Test') resp = await self.session.get(self.url) content = await resp.content.read() self.assertEqual(content, b'Test') @aioresponses() async def test_streaming_up_to(self, m): m.get(self.url, body='Test') resp = await self.session.get(self.url) content = await resp.content.read(2) self.assertEqual(content, b'Te') content = await resp.content.read(2) self.assertEqual(content, b'st') async def test_mocking_as_context_manager(self): with aioresponses() as aiomock: aiomock.add(self.url, payload={'foo': 'bar'}) resp = await self.session.get(self.url) self.assertEqual(resp.status, 200) payload = await resp.json() self.assertDictEqual(payload, {'foo': 'bar'}) def test_mocking_as_decorator(self): @aioresponses() def foo(loop, m): m.add(self.url, payload={'foo': 'bar'}) resp = loop.run_until_complete(self.session.get(self.url)) self.assertEqual(resp.status, 200) payload = loop.run_until_complete(resp.json()) self.assertDictEqual(payload, {'foo': 'bar'}) foo(self.loop) async def test_passing_argument(self): @aioresponses(param='mocked') async def foo(mocked): mocked.add(self.url, payload={'foo': 'bar'}) resp = await self.session.get(self.url) self.assertEqual(resp.status, 200) await foo() @fail_on(unused_loop=False) def test_mocking_as_decorator_wrong_mocked_arg_name(self): @aioresponses(param='foo') def foo(bar): # no matter what is here it should raise an error pass with self.assertRaises(TypeError) as cm: foo() exc = cm.exception self.assertIn("foo() got an unexpected keyword argument 'foo'", str(exc)) async def test_unknown_request(self): with aioresponses() as aiomock: aiomock.add(self.url, payload={'foo': 'bar'}) with self.assertRaises(ClientConnectionError): await self.session.get('http://example.com/foo') async def test_raising_exception(self): with aioresponses() as aiomock: url = 'http://example.com/Exception' aiomock.get(url, exception=Exception) with self.assertRaises(Exception): await self.session.get(url) url = 'http://example.com/Exception_object' aiomock.get(url, exception=Exception()) with self.assertRaises(Exception): await self.session.get(url) url = 'http://example.com/BaseException' aiomock.get(url, exception=BaseException) with self.assertRaises(BaseException): await self.session.get(url) url = 'http://example.com/BaseException_object' aiomock.get(url, exception=BaseException()) with self.assertRaises(BaseException): await self.session.get(url) url = 'http://example.com/CancelError' aiomock.get(url, exception=CancelledError) with self.assertRaises(CancelledError): await self.session.get(url) url = 'http://example.com/TimeoutError' aiomock.get(url, exception=TimeoutError) with self.assertRaises(TimeoutError): await self.session.get(url) url = 'http://example.com/HttpProcessingError' aiomock.get(url, exception=HttpProcessingError(message='foo')) with self.assertRaises(HttpProcessingError): await self.session.get(url) async def test_multiple_requests(self): """Ensure that requests are saved the way they would have been sent.""" with aioresponses() as m: m.get(self.url, status=200) m.get(self.url, status=201) m.get(self.url, status=202) json_content_as_ref = [1] resp = await self.session.get(self.url, json=json_content_as_ref) self.assertEqual(resp.status, 200) json_content_as_ref[:] = [2] resp = await self.session.get(self.url, json=json_content_as_ref) self.assertEqual(resp.status, 201) json_content_as_ref[:] = [3] resp = await self.session.get(self.url, json=json_content_as_ref) self.assertEqual(resp.status, 202) key = ('GET', URL(self.url)) self.assertIn(key, m.requests) self.assertEqual(len(m.requests[key]), 3) first_request = m.requests[key][0] self.assertEqual(first_request.args, tuple()) self.assertEqual(first_request.kwargs, { 'allow_redirects': True, "json": [1] }) second_request = m.requests[key][1] self.assertEqual(second_request.args, tuple()) self.assertEqual(second_request.kwargs, { 'allow_redirects': True, "json": [2] }) third_request = m.requests[key][2] self.assertEqual(third_request.args, tuple()) self.assertEqual(third_request.kwargs, { 'allow_redirects': True, "json": [3] }) async def test_request_with_non_deepcopyable_parameter(self): def non_deep_copyable(): """A generator does not allow deepcopy.""" for line in ["header1,header2", "v1,v2", "v10,v20"]: yield line generator_value = non_deep_copyable() with aioresponses() as m: m.get(self.url, status=200) resp = await self.session.get(self.url, data=generator_value) self.assertEqual(resp.status, 200) key = ('GET', URL(self.url)) self.assertIn(key, m.requests) self.assertEqual(len(m.requests[key]), 1) request = m.requests[key][0] self.assertEqual(request.args, tuple()) self.assertEqual(request.kwargs, { 'allow_redirects': True, "data": generator_value }) async def test_request_retrieval_in_case_no_response(self): with aioresponses() as m: with self.assertRaises(ClientConnectionError): await self.session.get(self.url) key = ('GET', URL(self.url)) self.assertIn(key, m.requests) self.assertEqual(len(m.requests[key]), 1) self.assertEqual(m.requests[key][0].args, tuple()) self.assertEqual(m.requests[key][0].kwargs, {'allow_redirects': True}) async def test_request_failure_in_case_session_is_closed(self): async def do_request(session): return (await session.get(self.url)) with aioresponses(): coro = do_request(self.session) await self.session.close() with self.assertRaises(RuntimeError) as exception_info: await coro assert str(exception_info.exception) == "Session is closed" async def test_address_as_instance_of_url_combined_with_pass_through(self): external_api = 'http://httpbin.org/status/201' async def doit(): api_resp = await self.session.get(self.url) # we have to hit actual url, # otherwise we do not test pass through option properly ext_rep = await self.session.get(URL(external_api)) return api_resp, ext_rep with aioresponses(passthrough=[external_api]) as m: m.get(self.url, status=200) api, ext = await doit() self.assertEqual(api.status, 200) self.assertEqual(ext.status, 201) async def test_pass_through_with_origin_params(self): external_api = 'http://httpbin.org/get' async def doit(params): # we have to hit actual url, # otherwise we do not test pass through option properly ext_rep = await self.session.get(URL(external_api), params=params) return ext_rep with aioresponses(passthrough=[external_api]) as m: params = {'foo': 'bar'} ext = await doit(params=params) self.assertEqual(ext.status, 200) self.assertEqual(str(ext.url), 'http://httpbin.org/get?foo=bar') @aioresponses() async def test_custom_response_class(self, m): class CustomClientResponse(ClientResponse): pass m.get(self.url, body='Test', response_class=CustomClientResponse) resp = await self.session.get(self.url) self.assertTrue(isinstance(resp, CustomClientResponse)) @aioresponses() def test_exceptions_in_the_middle_of_responses(self, mocked): mocked.get(self.url, payload={}, status=204) mocked.get( self.url, exception=ValueError('oops'), ) mocked.get(self.url, payload={}, status=204) mocked.get( self.url, exception=ValueError('oops'), ) mocked.get(self.url, payload={}, status=200) async def doit(): return (await self.session.get(self.url)) self.assertEqual(self.run_async(doit()).status, 204) with self.assertRaises(ValueError): self.run_async(doit()) self.assertEqual(self.run_async(doit()).status, 204) with self.assertRaises(ValueError): self.run_async(doit()) self.assertEqual(self.run_async(doit()).status, 200) @aioresponses() async def test_request_should_match_regexp(self, mocked): mocked.get(re.compile(r'^http://example\.com/api\?foo=.*$'), payload={}, status=200) response = await self.request(self.url) self.assertEqual(response.status, 200) @aioresponses() async def test_request_does_not_match_regexp(self, mocked): mocked.get(re.compile(r'^http://exampleexample\.com/api\?foo=.*$'), payload={}, status=200) with self.assertRaises(ClientConnectionError): await self.request(self.url) @aioresponses() def test_timeout(self, mocked): mocked.get(self.url, timeout=True) with self.assertRaises(asyncio.TimeoutError): self.run_async(self.request(self.url)) @aioresponses() def test_callback(self, m): body = b'New body' def callback(url, **kwargs): self.assertEqual(str(url), self.url) self.assertEqual(kwargs, {'allow_redirects': True}) return CallbackResult(body=body) m.get(self.url, callback=callback) response = self.run_async(self.request(self.url)) data = self.run_async(response.read()) assert data == body @aioresponses() def test_callback_coroutine(self, m): body = b'New body' event = asyncio.Event() async def callback(url, **kwargs): await event.wait() self.assertEqual(str(url), self.url) self.assertEqual(kwargs, {'allow_redirects': True}) return CallbackResult(body=body) m.get(self.url, callback=callback) future = asyncio.ensure_future(self.request(self.url)) self.run_async(asyncio.wait([future], timeout=0)) assert not future.done() event.set() self.run_async(asyncio.wait([future], timeout=0)) assert future.done() response = future.result() data = self.run_async(response.read()) assert data == body @aioresponses() async def test_exception_requests_are_tracked(self, mocked): kwargs = {"json": [42], "allow_redirects": True} mocked.get(self.url, exception=ValueError('oops')) with self.assertRaises(ValueError): await self.session.get(self.url, **kwargs) key = ('GET', URL(self.url)) mocked_requests = mocked.requests[key] self.assertEqual(len(mocked_requests), 1) request = mocked_requests[0] self.assertEqual(request.args, ()) self.assertEqual(request.kwargs, kwargs) async def test_possible_race_condition(self): async def random_sleep_cb(url, **kwargs): await asyncio.sleep(uniform(0.1, 1)) return CallbackResult(body='test') with aioresponses() as mocked: for i in range(20): mocked.get('http://example.org/id-{}'.format(i), callback=random_sleep_cb) tasks = [ self.session.get('http://example.org/id-{}'.format(i)) for i in range(20) ] await asyncio.gather(*tasks)
class AIOResponsesTestCase(TestCase): use_default_loop = False @asyncio.coroutine def setUp(self): self.url = 'http://example.com/api?foo=bar#fragment' self.session = ClientSession() super().setUp() @asyncio.coroutine def tearDown(self): close_result = self.session.close() if close_result is not None: yield from close_result super().tearDown() def run_async(self, coroutine: Union[Coroutine, Generator]): return self.loop.run_until_complete(coroutine) @asyncio.coroutine def request(self, url: str): return (yield from self.session.get(url)) @data( hdrs.METH_HEAD, hdrs.METH_GET, hdrs.METH_POST, hdrs.METH_PUT, hdrs.METH_PATCH, hdrs.METH_DELETE, hdrs.METH_OPTIONS, ) @patch('aioresponses.aioresponses.add') @fail_on(unused_loop=False) def test_shortcut_method(self, http_method, mocked): with aioresponses() as m: getattr(m, http_method.lower())(self.url) mocked.assert_called_once_with(self.url, method=http_method) @aioresponses() def test_returned_instance(self, m): m.get(self.url) response = self.run_async(self.session.get(self.url)) self.assertIsInstance(response, ClientResponse) @aioresponses() @asyncio.coroutine def test_returned_instance_and_status_code(self, m): m.get(self.url, status=204) response = yield from self.session.get(self.url) self.assertIsInstance(response, ClientResponse) self.assertEqual(response.status, 204) @aioresponses() @asyncio.coroutine def test_returned_response_headers(self, m): m.get(self.url, content_type='text/html', headers={'Connection': 'keep-alive'}) response = yield from self.session.get(self.url) self.assertEqual(response.headers['Connection'], 'keep-alive') self.assertEqual(response.headers[hdrs.CONTENT_TYPE], 'text/html') @aioresponses() @asyncio.coroutine def test_returned_response_raw_headers(self, m): m.get(self.url, content_type='text/html', headers={'Connection': 'keep-alive'}) response = yield from self.session.get(self.url) expected_raw_headers = ((b'Content-Type', b'text/html'), (b'Connection', b'keep-alive')) self.assertEqual(response.raw_headers, expected_raw_headers) @aioresponses() @asyncio.coroutine def test_raise_for_status(self, m): m.get(self.url, status=400) with self.assertRaises(ClientResponseError) as cm: response = yield from self.session.get(self.url) response.raise_for_status() self.assertEqual(cm.exception.message, http.RESPONSES[400][0]) @aioresponses() @asyncio.coroutine def test_returned_instance_and_params_handling(self, m): expected_url = 'http://example.com/api?foo=bar&x=42#fragment' m.get(expected_url) response = yield from self.session.get(self.url, params={'x': 42}) self.assertIsInstance(response, ClientResponse) self.assertEqual(response.status, 200) expected_url = 'http://example.com/api?x=42#fragment' m.get(expected_url) response = yield from self.session.get( 'http://example.com/api#fragment', params={'x': 42}) self.assertIsInstance(response, ClientResponse) self.assertEqual(response.status, 200) @aioresponses() def test_method_dont_match(self, m): m.get(self.url) with self.assertRaises(ClientConnectionError): self.run_async(self.session.post(self.url)) @aioresponses() @asyncio.coroutine def test_streaming(self, m): m.get(self.url, body='Test') resp = yield from self.session.get(self.url) content = yield from resp.content.read() self.assertEqual(content, b'Test') @aioresponses() @asyncio.coroutine def test_streaming_up_to(self, m): m.get(self.url, body='Test') resp = yield from self.session.get(self.url) content = yield from resp.content.read(2) self.assertEqual(content, b'Te') content = yield from resp.content.read(2) self.assertEqual(content, b'st') @asyncio.coroutine def test_mocking_as_context_manager(self): with aioresponses() as aiomock: aiomock.add(self.url, payload={'foo': 'bar'}) resp = yield from self.session.get(self.url) self.assertEqual(resp.status, 200) payload = yield from resp.json() self.assertDictEqual(payload, {'foo': 'bar'}) def test_mocking_as_decorator(self): @aioresponses() def foo(loop, m): m.add(self.url, payload={'foo': 'bar'}) resp = loop.run_until_complete(self.session.get(self.url)) self.assertEqual(resp.status, 200) payload = loop.run_until_complete(resp.json()) self.assertDictEqual(payload, {'foo': 'bar'}) foo(self.loop) @asyncio.coroutine def test_passing_argument(self): @aioresponses(param='mocked') @asyncio.coroutine def foo(mocked): mocked.add(self.url, payload={'foo': 'bar'}) resp = yield from self.session.get(self.url) self.assertEqual(resp.status, 200) yield from foo() @fail_on(unused_loop=False) def test_mocking_as_decorator_wrong_mocked_arg_name(self): @aioresponses(param='foo') def foo(bar): # no matter what is here it should raise an error pass with self.assertRaises(TypeError) as cm: foo() exc = cm.exception self.assertIn("foo() got an unexpected keyword argument 'foo'", str(exc)) @asyncio.coroutine def test_unknown_request(self): with aioresponses() as aiomock: aiomock.add(self.url, payload={'foo': 'bar'}) with self.assertRaises(ClientConnectionError): yield from self.session.get('http://example.com/foo') @asyncio.coroutine def test_raising_custom_error(self): with aioresponses() as aiomock: aiomock.get(self.url, exception=HttpProcessingError(message='foo')) with self.assertRaises(HttpProcessingError): yield from self.session.get(self.url) @asyncio.coroutine def test_multiple_requests(self): with aioresponses() as m: m.get(self.url, status=200) m.get(self.url, status=201) m.get(self.url, status=202) resp = yield from self.session.get(self.url) self.assertEqual(resp.status, 200) resp = yield from self.session.get(self.url) self.assertEqual(resp.status, 201) resp = yield from self.session.get(self.url) self.assertEqual(resp.status, 202) key = ('GET', URL(self.url)) self.assertIn(key, m.requests) self.assertEqual(len(m.requests[key]), 3) self.assertEqual(m.requests[key][0].args, tuple()) self.assertEqual(m.requests[key][0].kwargs, {'allow_redirects': True}) @asyncio.coroutine def test_address_as_instance_of_url_combined_with_pass_through(self): external_api = 'http://httpbin.org/status/201' @asyncio.coroutine def doit(): api_resp = yield from self.session.get(self.url) # we have to hit actual url, # otherwise we do not test pass through option properly ext_rep = yield from self.session.get(URL(external_api)) return api_resp, ext_rep with aioresponses(passthrough=[external_api]) as m: m.get(self.url, status=200) api, ext = yield from doit() self.assertEqual(api.status, 200) self.assertEqual(ext.status, 201) @aioresponses() @asyncio.coroutine def test_custom_response_class(self, m): class CustomClientResponse(ClientResponse): pass m.get(self.url, body='Test', response_class=CustomClientResponse) resp = yield from self.session.get(self.url) self.assertTrue(isinstance(resp, CustomClientResponse)) @aioresponses() def test_exceptions_in_the_middle_of_responses(self, mocked): mocked.get(self.url, payload={}, status=204) mocked.get( self.url, exception=ValueError('oops'), ) mocked.get(self.url, payload={}, status=204) mocked.get( self.url, exception=ValueError('oops'), ) mocked.get(self.url, payload={}, status=200) @asyncio.coroutine def doit(): return (yield from self.session.get(self.url)) self.assertEqual(self.run_async(doit()).status, 204) with self.assertRaises(ValueError): self.run_async(doit()) self.assertEqual(self.run_async(doit()).status, 204) with self.assertRaises(ValueError): self.run_async(doit()) self.assertEqual(self.run_async(doit()).status, 200) @aioresponses() @asyncio.coroutine def test_request_should_match_regexp(self, mocked): mocked.get(re.compile(r'^http://example\.com/api\?foo=.*$'), payload={}, status=200) response = yield from self.request(self.url) self.assertEqual(response.status, 200) @aioresponses() @asyncio.coroutine def test_request_does_not_match_regexp(self, mocked): mocked.get(re.compile(r'^http://exampleexample\.com/api\?foo=.*$'), payload={}, status=200) with self.assertRaises(ClientConnectionError): yield from self.request(self.url) @aioresponses() def test_timeout(self, mocked): mocked.get(self.url, timeout=True) with self.assertRaises(asyncio.TimeoutError): self.run_async(self.request(self.url)) @aioresponses() def test_callback(self, m): body = b'New body' def callback(url, **kwargs): self.assertEqual(str(url), self.url) self.assertEqual(kwargs, {'allow_redirects': True}) return CallbackResult(body=body) m.get(self.url, callback=callback) response = self.run_async(self.request(self.url)) data = self.run_async(response.read()) assert data == body
class AIOResponsesTestCase(TestCase): def setUp(self): self.url = 'http://example.com/api' self.loop = asyncio.get_event_loop() self.session = ClientSession() def tearDown(self): self.session.close() @data( hdrs.METH_GET, hdrs.METH_POST, hdrs.METH_PUT, hdrs.METH_PATCH, hdrs.METH_DELETE, hdrs.METH_OPTIONS, ) @patch('aioresponses.aioresponses.add') def test_shortcut_method(self, http_method, mocked): with aioresponses() as m: getattr(m, http_method.lower())(self.url) mocked.assert_called_once_with(self.url, method=http_method) @aioresponses() def test_returned_instance(self, m): m.get(self.url) response = self.loop.run_until_complete(self.session.get(self.url)) self.assertIsInstance(response, ClientResponse) @aioresponses() def test_returned_response_headers(self, m): m.get(self.url, content_type='text/html', headers={'Connection': 'keep-alive'}) response = self.loop.run_until_complete(self.session.get(self.url)) self.assertEqual(response.headers['Connection'], 'keep-alive') self.assertEqual(response.headers[hdrs.CONTENT_TYPE], 'text/html') @aioresponses() def test_method_dont_match(self, m): m.get(self.url) with self.assertRaises(ClientConnectionError): self.loop.run_until_complete(self.session.post(self.url)) def test_mocking_as_context_manager(self): with aioresponses() as aiomock: aiomock.add(self.url, payload={'foo': 'bar'}) resp = self.loop.run_until_complete(self.session.get(self.url)) self.assertEqual(resp.status, 200) payload = self.loop.run_until_complete(resp.json()) self.assertDictEqual(payload, {'foo': 'bar'}) def test_mocking_as_decorator(self): @aioresponses() def foo(m): m.add(self.url, payload={'foo': 'bar'}) resp = self.loop.run_until_complete(self.session.get(self.url)) self.assertEqual(resp.status, 200) payload = self.loop.run_until_complete(resp.json()) self.assertDictEqual(payload, {'foo': 'bar'}) foo() def test_passing_argument(self): @aioresponses(param='mocked') def foo(mocked): mocked.add(self.url, payload={'foo': 'bar'}) resp = self.loop.run_until_complete(self.session.get(self.url)) self.assertEqual(resp.status, 200) foo() def test_mocking_as_decorator_wrong_mocked_arg_name(self): @aioresponses(param='foo') def foo(bar): # no matter what is here it should raise an error pass with self.assertRaises(TypeError) as cm: foo() exc = cm.exception self.assertIn("foo() got an unexpected keyword argument 'foo'", str(exc)) def test_unknown_request(self): with aioresponses() as aiomock: aiomock.add(self.url, payload={'foo': 'bar'}) with self.assertRaises(ClientConnectionError): self.loop.run_until_complete( self.session.get('http://example.com/foo')) def test_multiple_requests(self): with aioresponses() as m: m.get(self.url, status=200) m.get(self.url, status=201) m.get(self.url, status=202) resp = self.loop.run_until_complete(self.session.get(self.url)) self.assertEqual(resp.status, 200) resp = self.loop.run_until_complete(self.session.get(self.url)) self.assertEqual(resp.status, 201) resp = self.loop.run_until_complete(self.session.get(self.url)) self.assertEqual(resp.status, 202)
def test_http_methods(self, patched): session = ClientSession(loop=self.loop) add_params = dict( headers={"Authorization": "Basic ..."}, max_redirects=2, encoding="latin1", version=aiohttp.HttpVersion10, compress="deflate", chunked=True, expect100=True, read_until_eof=False) run = self.loop.run_until_complete # Check GET run(session.get( "http://test.example.com", params={"x": 1}, **add_params)) self.assertEqual( patched.call_count, 1, "`ClientSession.request` not called") self.assertEqual( list(patched.call_args), [("GET", "http://test.example.com",), dict( params={"x": 1}, allow_redirects=True, **add_params)]) # Check OPTIONS run(session.options( "http://opt.example.com", params={"x": 2}, **add_params)) self.assertEqual( patched.call_count, 2, "`ClientSession.request` not called") self.assertEqual( list(patched.call_args), [("OPTIONS", "http://opt.example.com",), dict( params={"x": 2}, allow_redirects=True, **add_params)]) # Check HEAD run(session.head( "http://head.example.com", params={"x": 2}, **add_params)) self.assertEqual( patched.call_count, 3, "`ClientSession.request` not called") self.assertEqual( list(patched.call_args), [("HEAD", "http://head.example.com",), dict( params={"x": 2}, allow_redirects=False, **add_params)]) # Check POST run(session.post( "http://post.example.com", params={"x": 2}, data="Some_data", files={"x": '1'}, **add_params)) self.assertEqual( patched.call_count, 4, "`ClientSession.request` not called") self.assertEqual( list(patched.call_args), [("POST", "http://post.example.com",), dict( params={"x": 2}, data="Some_data", files={"x": '1'}, **add_params)]) # Check PUT run(session.put( "http://put.example.com", params={"x": 2}, data="Some_data", files={"x": '1'}, **add_params)) self.assertEqual( patched.call_count, 5, "`ClientSession.request` not called") self.assertEqual( list(patched.call_args), [("PUT", "http://put.example.com",), dict( params={"x": 2}, data="Some_data", files={"x": '1'}, **add_params)]) # Check PATCH run(session.patch( "http://patch.example.com", params={"x": 2}, data="Some_data", files={"x": '1'}, **add_params)) self.assertEqual( patched.call_count, 6, "`ClientSession.request` not called") self.assertEqual( list(patched.call_args), [("PATCH", "http://patch.example.com",), dict( params={"x": 2}, data="Some_data", files={"x": '1'}, **add_params)]) # Check DELETE run(session.delete( "http://delete.example.com", params={"x": 2}, **add_params)) self.assertEqual( patched.call_count, 7, "`ClientSession.request` not called") self.assertEqual( list(patched.call_args), [("DELETE", "http://delete.example.com",), dict( params={"x": 2}, **add_params)])
async def push_content(self, session: ClientSession, posts): url = self._format_template('content') session = session.post(url, json={'posts': posts}) return await self._get_response(session)
async def send_feedback(self, session: ClientSession, voting: Voting): url = self._format_template('feedback') session = session.post(url, json={'vote': voting._asdict()}) return await self._get_response(session)
class AIOResponseRedirectTest(TestCase): @asyncio.coroutine def setUp(self): self.url = "http://10.1.1.1:8080/redirect" self.session = ClientSession() super().setUp() @asyncio.coroutine def tearDown(self): close_result = self.session.close() if close_result is not None: yield from close_result super().tearDown() @aioresponses() @asyncio.coroutine def test_redirect_followed(self, rsps): rsps.get( self.url, status=307, headers={"Location": "https://httpbin.org"}, ) rsps.get("https://httpbin.org") response = yield from self.session.get( self.url, allow_redirects=True ) self.assertEqual(response.status, 200) self.assertEqual(str(response.url), "https://httpbin.org") self.assertEqual(len(response.history), 1) self.assertEqual(str(response.history[0].url), self.url) @aioresponses() @asyncio.coroutine def test_post_redirect_followed(self, rsps): rsps.post( self.url, status=307, headers={"Location": "https://httpbin.org"}, ) rsps.get("https://httpbin.org") response = yield from self.session.post( self.url, allow_redirects=True ) self.assertEqual(response.status, 200) self.assertEqual(str(response.url), "https://httpbin.org") self.assertEqual(response.method, "get") self.assertEqual(len(response.history), 1) self.assertEqual(str(response.history[0].url), self.url) @aioresponses() @asyncio.coroutine def test_redirect_missing_mocked_match(self, rsps): rsps.get( self.url, status=307, headers={"Location": "https://httpbin.org"}, ) with self.assertRaises(ClientConnectionError) as cm: yield from self.session.get( self.url, allow_redirects=True ) self.assertEqual( str(cm.exception), 'Connection refused: GET http://10.1.1.1:8080/redirect' ) @aioresponses() @asyncio.coroutine def test_redirect_missing_location_header(self, rsps): rsps.get(self.url, status=307) response = yield from self.session.get(self.url, allow_redirects=True) self.assertEqual(str(response.url), self.url) @aioresponses() @asyncio.coroutine @skipIf(condition=AIOHTTP_VERSION < '3.1.0', reason='aiohttp<3.1.0 does not add request info on response') def test_request_info(self, rsps): rsps.get(self.url, status=200) response = yield from self.session.get(self.url) request_info = response.request_info assert str(request_info.url) == self.url assert request_info.headers == {} @aioresponses() @asyncio.coroutine @skipIf(condition=AIOHTTP_VERSION < '3.1.0', reason='aiohttp<3.1.0 does not add request info on response') def test_request_info_with_original_request_headers(self, rsps): headers = {"Authorization": "Bearer access-token"} rsps.get(self.url, status=200) response = yield from self.session.get(self.url, headers=headers) request_info = response.request_info assert str(request_info.url) == self.url assert request_info.headers == headers
class GeppyttoApiClient: def __init__(self, server_base_url: str): server_base_url = urljoin(server_base_url, '/api/internal/v1/') self.server_base_url = server_base_url self._url_get_agent_info = urljoin(server_base_url, './agent') self._url_bind_to_free_slot = urljoin(server_base_url, './agent/bind_to_free_slot') self._url_agent_heartbeat = urljoin(server_base_url, './agent/agent_heartbeat') self._url_remove_agent = urljoin(server_base_url, './agent/remove_agent') self._url_add_browser_agent_map = urljoin( server_base_url, './browser_agent_map/add_browser_agent_map') self._url_delete_browser_agent_map = urljoin( server_base_url, './browser_agent_map/delete_browser_agent_map') self._url_add_busy_event = urljoin(server_base_url, './busy_event/add_busy_event') self.session = ClientSession() self._access_token = '' def set_access_token(self, token): self._access_token = token async def close(self): await self.session.close() async def get_agent_info(self, id_: str = None, name: str = None): params = {} if id_ is not None: params['id'] = id_ if name is not None: params['name'] = name async with self.session.get(self._url_get_agent_info, params=params) as resp: return await resp.json() async def bind_to_free_slot(self, advertise_address: str, is_steady: bool, bind_token: str): async with self.session.post(self._url_bind_to_free_slot, json={ 'advertise_address': advertise_address, 'is_steady': is_steady, 'bind_token': bind_token, }) as resp: return await resp.json() async def agent_heartbeat(self, agent_id: str, last_ack_time: int, busy_level: int): params = {} if agent_id is not None: params['agent_id'] = agent_id params['last_ack_time'] = last_ack_time params['busy_level'] = busy_level async with self.session.get( self._url_agent_heartbeat, params=params, headers={'X-GEPPYTTO-ACCESS-TOKEN': self._access_token}) as resp: return await resp.json() async def remove_agent(self, agent_id: int, user_id: int, is_steady: bool): data = { 'agent_id': agent_id, 'user_id': user_id, 'is_steady': is_steady } async with self.session.delete( self._url_remove_agent, json=data, headers={'X-GEPPYTTO-ACCESS-TOKEN': self._access_token}) as resp: return await resp.json() async def delete_browser_agent_map(self, user_id: int = None, bid: str = None, agent_id: int = None): if user_id is not None and bid is not None: params = {'user_id': user_id, 'bid': bid} elif agent_id is not None: params = {'agent_id': agent_id} else: return None async with self.session.delete( self._url_delete_browser_agent_map, params=params, headers={'X-GEPPYTTO-ACCESS-TOKEN': self._access_token}) as resp: return await resp.json() async def add_browser_agent_map(self, user_id: int, bid: str, agent_id: int): async with self.session.post( self._url_add_browser_agent_map, json={ 'agent_id': agent_id, 'user_id': user_id, 'bid': bid }, headers={'X-GEPPYTTO-ACCESS-TOKEN': self._access_token}) as resp: return await resp.json() async def add_busy_event(self, user_id: int, agent_id: int): async with self.session.post( self._url_add_busy_event, json={ 'agent_id': agent_id, 'user_id': user_id }, headers={'X-GEPPYTTO-ACCESS-TOKEN': self._access_token}) as resp: return await resp.json()