Lesson 5 of 6
Consuming and mocking SAP S/4HANA APIs
10 min
Listen to this lesson
The fleet app shows sales order status from SAP S/4HANA. In CAP, a remote API becomes a remote service: you import its specification, and CAP lets you query it with the same APIs you use for local entities. The big win for testing is that CAP can mock the imported service from its definition, so most development and tests run without CMD, CMQ or a network connection.
Importing the API
Kenji's team downloads the EDMX specification of the Sales Order (A2X) API, API_SALES_ORDER_SRV, from the SAP Business Accelerator Hub and runs cds import API_SALES_ORDER_SRV.edmx --as cds. CAP writes a CDS service definition to srv/external and adds an entry under cds.requires in package.json with kind: odata-v2 (OData V4 inputs become odata, OpenAPI becomes rest) and the model path. The imported file is now part of the source and the contract that tests check.
Calling it from the fleet service
The fleet service exposes a read-only projection of the remote sales order entity and delegates reads to the remote service:const s4 = await cds.connect.to('API_SALES_ORDER_SRV')this.on('READ', 'SalesOrders', req => s4.run(req.query))
CAP translates the query into an OData V2 request. Limit what you read: select only the fields you show, filter by the customer, and page results. Remote calls are slower and less reliable than local reads, so handle errors and time-outs deliberately instead of letting a failed call break the inquiry screen.
Mocked out of the box
When no credentials are configured for the remote service, cds watch mocks it in-process and logs that it is doing so. Mock data comes from .csv files named after the service and entity, for example srv/external/data/API_SALES_ORDER_SRV-A_SalesOrder.csv. To run the mock as a separate process, closer to the real setup, start cds mock API_SALES_ORDER_SRV in one terminal and cds watch in another; the app then connects to the mock over HTTP instead of serving it in-process. CAP's documentation describes the imported APIs as the contracts that let teams work in parallel.
| Mode | How you start it | What the app talks to | Use it for |
|---|---|---|---|
| In-process mock | cds watch with no credentials for the remote service | The imported definition served from the local database with .csv data | Daily development and fast automated tests |
| Separate mock process | cds mock API_SALES_ORDER_SRV, then cds watch | A local mock server over HTTP | Checking the remote call path and error handling |
| Hybrid | cds bind to service instances, then cds watch --profile hybrid | Real destination and SAP S/4HANA (CMD) through SAP BTP | Checking real data shapes and connectivity before deployment |
| Deployed | MTA deployed to a subaccount | The destination configured in that subaccount | Integration and end-to-end tests in cmc-ext-test |
Real connections per profile
For deployment, credentials go under a profile so they do not switch off the local mock. In package.json, a [production] block for API_SALES_ORDER_SRV sets credentials.destination to the destination name (Contoso uses CMC_S4HANA in every subaccount, each pointing at its paired system) and credentials.path to /sap/opu/odata/sap/API_SALES_ORDER_SRV. Because CMD, CMQ and CMP are private systems, the project also needs the destination and connectivity services; cds add xsuaa,destination,connectivity adds them. For hybrid testing, developers bind to real service instances with cds bind and run with --profile hybrid.
- Fiori appThe fleet desk opens the sales orders for Great Lakes Fleet Services
- FleetServiceThe on READ handler for SalesOrders delegates the query to the remote service
- Remote serviceCAP translates the CQL query into an OData V2 request for API_SALES_ORDER_SRV
- Destination CMC_S4HANAThe subaccount's destination supplies the virtual URL and authentication
- Cloud ConnectorThe tunnel forwards the call to the exposed path on the paired system
- SAP S/4HANACMQ client 100 in test, CMP in production, returns the orders the API user may read
That replacement is both the strength and the trap of mocking. Everything after the remote service in the read path, the destination, the tunnel, the remote user's authorizations and the real data, is invisible to a local run. Local tests therefore prove the app's own logic and its use of the API contract; they cannot prove connectivity or permissions. Plan at least one integration test per remote call in cmc-ext-test, and record which tests ran against mocks and which against CMQ so that nobody mistakes one for the other in the sign-off evidence.
What would you do?
Locally, the fleet app works perfectly against mocked sales orders. In cmc-ext-test, the sales order list is empty for every user, with no error shown. What should Priya's team check first?
- cds import turns an API specification into a CDS service in srv/external and registers it in cds.requires.
- Query remote services with cds.connect.to and CQL; select, filter and page what you need.
- Without credentials, cds watch mocks imported services in-process using .csv data; cds mock runs them separately.
- Put real credentials (destination name and path) in the [production] profile; use cds bind and the hybrid profile for real checks.
- Make mock data realistic, including awkward cases, but never copied from production.
Check your understanding · not graded
Lesson check
1. Where does cds import write the CDS definition of an imported API?
2. When does cds watch mock an imported remote service in-process?
3. Which file name provides mock rows for the A_SalesOrder entity of API_SALES_ORDER_SRV?
4. Why are the production credentials placed under a [production] profile?