Skip to content

Commit ea558f5

Browse files
authored
tests: add httpx async client integration test (#255)
1 parent 35f3002 commit ea558f5

File tree

1 file changed

+144
-0
lines changed

1 file changed

+144
-0
lines changed
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
""" Test the pyodata integration with httpx client
2+
3+
- it provided sync, requests like interface
4+
- it provides asyncio interface as well - FOCUS OF THIS TEST MODULE
5+
6+
https://www.python-httpx.org/
7+
"""
8+
9+
import httpx
10+
from httpx import Response
11+
import respx
12+
import pytest
13+
14+
import pyodata.v2.service
15+
from pyodata import Client
16+
from pyodata.exceptions import PyODataException, HttpError
17+
from pyodata.v2.model import ParserError, PolicyWarning, PolicyFatal, PolicyIgnore, Config
18+
19+
SERVICE_URL = 'http://example.com'
20+
21+
def test_invalid_odata_version():
22+
"""Check handling of request for invalid OData version implementation"""
23+
24+
with pytest.raises(PyODataException) as e_info:
25+
pyodata.Client(SERVICE_URL, httpx, 'INVALID VERSION')
26+
27+
assert str(e_info.value).startswith('No implementation for selected odata version')
28+
29+
30+
def test_create_client_for_local_metadata(metadata):
31+
"""Check client creation for valid use case with local metadata"""
32+
33+
client = pyodata.Client(SERVICE_URL, httpx, metadata=metadata)
34+
35+
assert isinstance(client, pyodata.v2.service.Service)
36+
assert client.schema.is_valid == True
37+
assert len(client.schema.entity_sets) != 0
38+
39+
40+
@pytest.mark.parametrize("content_type", ['application/xml', 'application/atom+xml', 'text/xml'])
41+
def test_create_service_application(respx_mock, metadata, content_type):
42+
"""Check client creation for valid MIME types"""
43+
44+
# Note: respx_mock is provided by respx package as pytest helper
45+
headers = httpx.Headers(
46+
{'Content-Type': content_type}
47+
)
48+
49+
respx_mock.get(f"{SERVICE_URL}/$metadata").mock(
50+
return_value=Response(status_code=200,
51+
content=metadata,
52+
headers=headers,
53+
)
54+
)
55+
56+
client = pyodata.Client(SERVICE_URL, httpx)
57+
assert isinstance(client, pyodata.v2.service.Service)
58+
59+
# one more test for '/' terminated url
60+
client = pyodata.Client(SERVICE_URL + '/', httpx)
61+
assert isinstance(client, pyodata.v2.service.Service)
62+
assert client.schema.is_valid
63+
64+
65+
def test_metadata_not_reachable(respx_mock):
66+
"""Check handling of not reachable service metadata"""
67+
68+
headers = httpx.Headers(
69+
{'Content-Type': 'text/html'}
70+
)
71+
72+
respx_mock.get(f"{SERVICE_URL}/$metadata").mock(
73+
return_value=Response(status_code=404,
74+
headers=headers,
75+
)
76+
)
77+
78+
with pytest.raises(HttpError) as e_info:
79+
pyodata.Client(SERVICE_URL, httpx)
80+
81+
assert str(e_info.value).startswith('Metadata request failed')
82+
83+
84+
def test_metadata_saml_not_authorized(respx_mock):
85+
"""Check handling of not SAML / OAuth unauthorized response"""
86+
87+
headers = httpx.Headers(
88+
{'Content-Type': 'text/html; charset=utf-8'}
89+
)
90+
91+
respx_mock.get(f"{SERVICE_URL}/$metadata").mock(
92+
return_value=Response(status_code=200,
93+
headers=headers,
94+
)
95+
)
96+
97+
with pytest.raises(HttpError) as e_info:
98+
pyodata.Client(SERVICE_URL, httpx)
99+
100+
assert str(e_info.value).startswith('Metadata request did not return XML, MIME type:')
101+
102+
103+
def test_client_custom_configuration(respx_mock,metadata):
104+
"""Check client creation for custom configuration"""
105+
106+
headers = httpx.Headers(
107+
{'Content-Type': 'application/xml'}
108+
)
109+
110+
respx_mock.get(f"{SERVICE_URL}/$metadata").mock(
111+
return_value=Response(status_code=200,
112+
headers=headers,
113+
content=metadata,
114+
)
115+
)
116+
117+
namespaces = {
118+
'edmx': "customEdmxUrl.com",
119+
'edm': 'customEdmUrl.com'
120+
}
121+
122+
custom_config = Config(
123+
xml_namespaces=namespaces,
124+
default_error_policy=PolicyFatal(),
125+
custom_error_policies={
126+
ParserError.ANNOTATION: PolicyWarning(),
127+
ParserError.ASSOCIATION: PolicyIgnore()
128+
})
129+
130+
with pytest.raises(PyODataException) as e_info:
131+
client = pyodata.Client(SERVICE_URL, httpx, config=custom_config, namespaces=namespaces)
132+
133+
assert str(e_info.value) == 'You cannot pass namespaces and config at the same time'
134+
135+
with pytest.warns(DeprecationWarning,match='Passing namespaces directly is deprecated. Use class Config instead'):
136+
client = pyodata.Client(SERVICE_URL, httpx, namespaces=namespaces)
137+
138+
assert isinstance(client, pyodata.v2.service.Service)
139+
assert client.schema.config.namespaces == namespaces
140+
141+
client = pyodata.Client(SERVICE_URL, httpx, config=custom_config)
142+
143+
assert isinstance(client, pyodata.v2.service.Service)
144+
assert client.schema.config == custom_config

0 commit comments

Comments
 (0)