I'm having a hard time testing zeep actions while offline. I'm using pytest-vcr to record the initial test. When I run my tests a subsequent time, they fail even though a cassette exists for the interaction. I suspect that zeep tries to communicate to the server before I call RISClient.nodes()
. I thought it did so to download the WSDL, so I implemented a local_wsdl
parameter in RISClient
to make the WSDL available locally. However, after testing with that argument set to True
, I get the following error: executeCCMSQLStatement Error: HTTPSConnectionPool(host='x.x.x.x', port=8443): Max retries exceeded with url: /realtimeservice2/services/RISService (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x00000166EB1701D0>: Failed to establish a new connection: [WinError 10065] A socket operation was attempted to an unreachable host')).
When I test with local_wsdl
set to False
, the error that I get is: E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='x.x.x.x', port=8443): Max retries exceeded with url: /realtimeservice2/services/RISService?wsdl (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x0000024C1C5EBED0>: Failed to establish a new connection: [WinError 10065] A socket operation was attempted to an unreachable host'))
Why is my test failing offline? And, how can I get it to pass?
lib\utils\clients.py
class SOAPClient:
def __init__(
self,
host,
user,
password,
binding=None,
wsdl=None,
service_path=None
):
log.debug(f'The WSDL is set to: {wsdl}')
session = Session()
session.verify = False
requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning) # noqa
session.auth = HTTPBasicAuth(user, password)
transport = Transport(session=session, timeout=10)
settings = Settings(strict=False, xml_huge_tree=True)
plugin = [MyLoggingPlugin()]
self._client = Client(
wsdl=f'{wsdl}',
settings=settings,
transport=transport,
plugins=plugin
)
self._binding = binding
self._host = host
self._service_path = service_path
self._service = None
def execute_request(self, service_name: str, criteria: dict):
if self._service is None:
self._service = self._client.create_service(
binding_name=f'{{http://schemas.cisco.com/ast/soap}}{self._binding}Binding',
address=f'https://{self._host}:8443/{self._service_path}'
try:
resp = self._service[service_name](**criteria)
except Exception as e:
print('*' * 80)
print(f'{service_name} Error: {e}')
else:
return resp
class RISClient(SOAPClient):
def __init__(self, host, user, password, local_wsdl):
binding = 'Ris'
service_path = 'realtimeservice2/services/RISService'
if local_wsdl:
wsdl = r'C:\Users\user\Downloads\wsdl\RISService.xml'
else:
wsdl = f'https://{host}:8443/{service_path}?wsdl'
super().__init__(host, user, password, binding, wsdl, service_path)
def nodes(self):
columns = {
'ExecuteSQLInputData': "SELECT name FROM processnode WHERE nodeid>'1'", # noqa
'GetColumns': {
'ColumnName': 'name'
}
}
resp = self.execute_request('executeCCMSQLStatement', columns)
nodes = [node['Value']['_value_1'] for node in resp]
return nodes
tests\conftest.py
@pytest.fixture(scope='session')
def vcr_config():
return {
'filter_headers': [('authorization', 'Secret')],
'record_mode': 'new_episodes',
'match_on': ['method', 'uri'],
}
tests\test_clients.py
from lib.utils.clients import RISClient
@pytest.mark.vcr()
def test_ris(env_conf):
conf = env_conf
ris_client = RISClient(conf.ip, conf.user, conf.password, local_wsdl=True)
nodes = ris_client.nodes()
assert len(nodes) == 3