Mocking
Policies often depend on external data through functions and attribute finders (PIPs). In tests, these dependencies are replaced with mocks that return controlled values.
Function Mocking
A function mock intercepts calls to a SAPL function and returns a predefined value:
given
- function time.dayOfWeek("2026-01-15T10:00:00Z") maps to "WEDNESDAY"
No parameters:
- function system.timestamp() maps to "2026-01-15T10:00:00Z"
Matching any argument:
- function time.dayOfWeek(any) maps to "FRIDAY"
Multiple parameters with mixed matchers:
- function string.concat("hello", " ", any) maps to "hello world"
Typed matchers:
- function time.dayOfWeek(matching text) maps to "MONDAY"
- function math.process(matching number) maps to 100
- function logic.check(matching boolean) maps to true
- function json.transform(matching object) maps to {}
- function collection.process(matching array) maps to []
- function util.handle(matching null) maps to "handled"
Matching a specific value within a type:
- function time.dayOfWeek(matching text "2026-01-15T10:00:00Z") maps to "WEDNESDAY"
Error and Undefined Returns
Mocks can return error or undefined values:
- function service.fetch(any) maps to error
- function service.fetch(any) maps to error("Service unavailable")
- function lookup.find(any) maps to undefined
An error return causes the enclosing policy condition to evaluate to INDETERMINATE. An undefined return behaves like a missing value.
Environment Attribute Mocking
Environment attributes are accessed in policies as <pip.attribute>. Each mock requires a unique mock ID (a string you choose) that identifies the mock for later operations like streaming and verification.
given
- attribute "timeMock" <time.now> emits "2026-01-15T10:00:00Z"
The emits clause sets the initial value. Omit it to create a mock without an initial value (useful when the first value is emitted in a then block):
- attribute "statusMock" <system.status>
With argument matchers:
- attribute "timeMock" <time.now(any)> emits "2026-01-15T10:00:00Z"
- attribute "configMock" <system.config("timeout")> emits 30
Error and undefined:
- attribute "failMock" <service.status> emits error("Connection refused")
- attribute "failMock" <service.status> emits error
- attribute "missingMock" <data.value> emits undefined
Entity Attribute Mocking
Entity attributes are accessed in policies as value.<pip.attribute>. The mock specifies a matcher for the entity (left-hand) value:
Any entity:
- attribute "upperMock" any.<string.upper> emits "HELLO"
Exact entity value:
- attribute "upperMock" "hello".<string.upper> emits "HELLO"
- attribute "profileMock" 42.<user.profile> emits { "name": "Alice" }
- attribute "flagMock" true.<config.flag> emits "enabled"
- attribute "dataMock" { "id": 1 }.<record.details> emits { "status": "active" }
Typed entity matcher:
- attribute "validMock" matching text.<x509.isValid> emits true
- attribute "processMock" matching object.<data.process> emits { "result": "ok" }
Entity attribute with parameters:
- attribute "qualMock" "Alice".<employee.qualification("IT")> emits ["Java", "Python"]
- attribute "msgMock" any.<mqtt.messages(1, any)> emits { "payload": "data" }
Mock ID
The mock ID is a string that uniquely identifies an attribute mock within a scenario. It serves two purposes:
- Streaming: The
thenblock uses the mock ID to emit new values mid-test (see Streaming Tests). - Verification: The
verifyblock can reference mocks by their attribute name to check call counts (see Verification).
Choose descriptive IDs that reflect what the mock represents:
- attribute "currentTime" <time.now> emits "2026-01-15T10:00:00Z"
- attribute "userLocation" any.<geo.location> emits { "lat": 48.1, "lon": 11.6 }