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