Testing OData connections
OData mocks - entity sets, single entities, adapters and the live OData test server.
When your Zato service reads customers from Business Central, queries sales orders in S/4HANA, or looks up employees in SuccessFactors, you need to test that logic without a real backend. This page shows how to mock OData responses so your tests run fast and don't require access to the actual systems.
Note: If you're new to unit testing with Zato, check the tutorial first.
Basic usage
Services access OData connections like this:
from zato.server.service import Service
class GetCustomersByCity(Service):
name = 'odata.customers.by-city'
input = 'city'
def handle(self):
conn = self.odata['Business Central']
customers = conn.read('customers',
filter=f"city eq '{self.request.input.city}'",
orderby='displayName',
)
self.response.payload = {
'customers': [{'name': c['displayName'], 'city': c['city']} for c in customers]
}
Mock the OData results in your test:
from zato_testing import ServiceTestCase
from myapp.services import GetCustomersByCity
class TestGetCustomersByCity(ServiceTestCase):
def test_returns_customers(self):
# Configure OData results with the odata: prefix
self.set_response('odata:Business Central', [
{'id': 'c1', 'displayName': 'Adatum Corporation', 'city': 'London'},
{'id': 'c2', 'displayName': 'Trey Research', 'city': 'London'},
])
service = self.invoke(GetCustomersByCity, city='London')
self.assertEqual(len(service.response.payload['customers']), 2)
self.assertEqual(service.response.payload['customers'][0]['name'], 'Adatum Corporation')
Note the odata: prefix to distinguish OData connections from REST connections.
Single entities
Services that read one entity by key use .get - mock a single dict:
class GetCustomer(Service):
name = 'odata.customer.get'
input = 'customer_id'
def handle(self):
conn = self.odata['Business Central']
customer = conn.get('customers', self.request.input.customer_id)
self.response.payload = {'name': customer['displayName']}
class TestGetCustomer(ServiceTestCase):
def test_returns_customer(self):
self.set_response('odata:Business Central', {
'id': 'c1', 'displayName': 'Adatum Corporation', 'city': 'London'
})
service = self.invoke(GetCustomer, customer_id='c1')
self.assertEqual(service.response.payload['name'], 'Adatum Corporation')
Empty results
Test handling of entities not found:
class TestNoCustomers(ServiceTestCase):
def test_handles_empty_set(self):
self.set_response('odata:Business Central', [])
service = self.invoke(GetCustomersByCity, city='Atlantis')
self.assertEqual(service.response.payload['customers'], [])
Adapters
Services built on ODataAdapter are tested the same way - the mocked results are what self._invoke_odata() returns:
from zato.server.service import ODataAdapter
class CustomersByCity(ODataAdapter):
name = 'odata.adapter.customers-by-city'
conn_name = 'Business Central'
entity_set = 'customers'
filter = "city eq '{city}'"
def handle(self):
items = self._invoke_odata()
self.response.payload = {'items': items}
class TestCustomersByCity(ServiceTestCase):
def test_maps_items(self):
self.set_response('odata:Business Central', [
{'id': 'c1', 'displayName': 'Adatum Corporation', 'city': 'London'},
])
service = self.invoke(CustomersByCity, city='London')
self.assertEqual(len(service.response.payload['items']), 1)
Live testing with the OData test server
Beyond unit tests, Zato ships with an in-process OData test server that speaks both V2 and V4 and simulates the auth and validation behavior of S/4HANA, SuccessFactors, Dynamics 365 Finance and Operations and Business Central - including SAP CSRF token exchanges, OAuth2 token endpoints and server-driven paging. It records every request it receives, which lets integration tests assert both the mapped output and what actually went over the wire.