sup?

Projects

Mock enterprise systems for integration testing. Point your code at them and develop, test and demo without a license, a VPN tunnel, or a support ticket.

Using them together: Testing an SAP-to-EDI integration without SAP or a trading partner.

mock-sap

A black-box mock SAP endpoint. It speaks the shapes, not the business logic: SAP Gateway OData V2 and V4 services, BAPI/RFC calls over JSON and SOAP, and IDocs in XML and flat-file form, all backed by SQLite.

  • Zero dependencies. Python 3.8+ standard library and SQLite.
  • Real wire shapes. __metadata, /Date(…)/, EDMX $metadata, CSRF tokens, $batch changesets, BAPIRET2 tables.
  • V2 and V4 over the same rows. $apply aggregation, delta tokens, Fiori UI annotations, and OAuth 2.0 token flows a client can expire and refresh.
  • Deterministic demo data. Business partners, products, sales and purchase orders, the same every run for a given seed.
  • Failure on demand. Latency, 500s, locked documents, expired CSRF tokens.
pip install mock-sap
mock-sap --port 8000
curl "http://127.0.0.1:8000/sap/opu/odata/sap/API_SALES_ORDER_SRV/A_SalesOrder?\$top=1&\$format=json"

mock-edi

A mock EDI trading partner. Not an EDI library or an AS2 server, but the thing on the other end. Send it an 850 and it answers with a 997, an 855, an 856 and an 810. Send it EDIFACT ORDERS and you get CONTRL, ORDRSP, DESADV and INVOIC.

   you ──850──▶  mock-edi
       ◀──997──  the syntax parsed
       ◀──855──  2 lines: one confirmed, one short
       ◀──856──  shipment / order / item, with a tracking number
       ◀──810──  1132.80, terms 2% 10 net 30
  • Zero dependencies. Installs in a locked-down CI image.
  • X12 and EDIFACT over AS2. Fixed-width ISA, release characters, HL trees, MDNs with a Received-Content-MIC.
  • AS2, plain HTTP, or a folder. Point --drop-dir and --pickup-dir at directories for integrations that still trade files.
  • Changes and receipts. An 860 changes an order and is answered with an 865; EDIFACT's ORDCHG is answered by an ORDRSP, having no change acknowledgment of its own. The 997s you send back are matched to what the mock sent, so "nobody acknowledged my invoice" is testable.
  • Failure on demand. Short shipments, rejected lines, duplicate invoices, a strict partner, a partner that never answers.
  • Validates its own output against the same dictionary it checks yours against.
pip install mock-edi
mock-edi --port 8080
curl -X POST --data-binary @order.edi http://127.0.0.1:8080/edi

PO bridge mock-sap + mock-edi

A worked example of the two mocks together. po_bridge.py reads a purchase order from SAP over OData, sends it to the supplier as an X12 850, and posts the supplier's 855 back into SAP as an ORDRSP IDoc. Any line that isn't a clean confirmation comes back as an exception for a buyer to look at.

send:     SAP PO (OData)  ──▶  X12 850  ──▶  supplier
receive:  SAP  ◀──  ORDRSP IDoc  ◀──  X12 855  ◀──  supplier
  • The supplier confirms everything, and one IDoc lands in SAP.
  • The supplier ships short, and both short lines are flagged.
  • The supplier refuses a line, and SAP's IDoc carries the rejection on the right item.
  • The supplier never answers, and nothing is posted: the case a chase-up alert is for.
  • SAP is down when the 855 arrives, and the confirmation is kept until SAP takes it. This test found a real bug.
git clone https://github.com/rseufert/mock-edi && cd mock-edi
pip install mock-sap
mock-sap --port 8000 &
python3 -m mockedi --port 8080 &
cd examples && python3 -m unittest -v test_po_bridge

Invoice check mock-sap + mock-edi

What happens after the goods ship. invoice_check.py is accounts-payable middleware: it takes a supplier's X12 810 invoice and posts it into SAP as an INVOIC IDoc only if it passes a three-way match against the purchase order and the 856 ship notice. Anything else is blocked, with the reasons.

PO (SAP)  ──┐
856 ship  ──┼──▶  match?  ──▶  yes: INVOIC IDoc into SAP
810 bill  ──┘                  no:  blocked, with reasons
  • A clean invoice is posted, and the test reads back what SAP received.
  • A short shipment, billed as shipped, is posted. Matching against the ordered quantity would wrongly block it.
  • A price disagreement is blocked. mock-edi bills its own catalogue price, the way real suppliers do.
  • The same invoice sent twice is posted once. No sleeping: the test advances mock-edi's clock.
git clone https://github.com/rseufert/mock-sap && cd mock-sap
pip install mock-edi
python3 -m mocksap --port 8000 &
mock-edi --port 8080 &
cd examples && python3 -m unittest -v test_invoice_check