Class HttpChaosProfile
Retry-After header), latency injection, and
response-body corruption (truncateBodyAtFraction keeps only a leading
fraction of the body bytes; malformedBody appends a broken-JSON
fragment) for testing client-side body-parsing resilience, and a slow
("dribbled") response (slowResponseChunkSize + slowResponseChunkDelay
send the body in small chunks with a delay between each) for testing read
timeouts on a trickling response.
Body corruption and slow-response are deterministic (no probability draw): they apply to the real (non-error) response whenever the count and time windows are eligible, and are skipped for streaming bodies. Connection-drop and error injection take priority — when an error is injected the synthetic error body is returned uncorrupted and at full speed.
It also carries an optional stateful request quota (a fixed-window
rate limit): when quotaName, quotaLimit and
quotaWindowMillis are set, requests beyond quotaLimit within
the window are rejected with quotaErrorStatus (default 429) and the
retryAfter header. Unlike the probabilistic error this is deterministic
and counts real requests across the process (see
HttpQuotaRegistry); expectations sharing
a quotaName share one counter. The quota gate takes priority over the
probabilistic error and the body/slow faults (after connection-drop).
It can also model gradual degradation: when degradationRampMillis
is set, the probabilistic fault rates (errorProbability and
dropConnectionProbability) ramp linearly from 0.0 at the
expectation's first match up to their configured values once the ramp duration
has elapsed, so a dependency appears to deteriorate over time (useful for
alerting / SLO-burn tests). The ramp is measured with the controllable clock
(deterministic under freeze/advance) and does not affect the deterministic
faults (latency, body corruption, slow response, quota).
Attach to an Expectation via
expectation.withChaos(httpChaosProfile()...) to inject faults into
the following action types:
- Mocked responses: RESPONSE, RESPONSE_TEMPLATE, RESPONSE_CLASS_CALLBACK
- Forward actions: FORWARD, FORWARD_TEMPLATE, FORWARD_CLASS_CALLBACK, FORWARD_REPLACE, FORWARD_VALIDATE
Determinism: with errorProbability of 1.0 (always) or
0.0/null (never) the error decision is fully deterministic. A
fractional probability draws once per response; set seed to make that
single draw reproducible (note: a fixed seed yields the same decision every
time).
Count-based stateful fault window: succeedFirst and
failRequestCount define a window over the expectation's 1-based
match count where chaos is eligible:
- Matches 1..succeedFirst are NOT eligible (chaos is suppressed).
- Matches (succeedFirst+1)..(succeedFirst+failRequestCount) ARE eligible.
- Matches beyond succeedFirst+failRequestCount recover (no chaos).
null every match is eligible, preserving
backward compatibility. The window check is deterministic and composes
with the probabilistic error draw: a match must be within the window AND
pass the probability check to receive an injected fault.
Time-based outage window: outageAfterMillis and
outageDurationMillis define a self-healing window, measured relative
to the expectation's first match, during which chaos is active. The window
opens outageAfterMillis ms after the first match and (when a duration
is set) closes after outageDurationMillis ms, after which the service
behaves normally again. The window is measured with the controllable clock
(TimeService), so freezing/advancing the clock
(e.g. via PUT /mockserver/clock) makes it deterministic in tests. It
composes with the count window and the probability draws: a fault fires only
when the request is inside the time window AND the count window AND the draw
passes. When both fields are null there is no time gate.
Follows the model field/withX/getter convention so it round-trips
without a bespoke (de)serializer.
-
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptioncopy()Returns a copy of this profile with all fields duplicated.booleancountWindowEligible(int matchCount) Returnstruewhen the given 1-based match count falls within the chaos-eligible window defined bysucceedFirstandfailRequestCount.doubledegradationFactor(long firstMatchEpochMillis, long nowEpochMillis) Returns the gradual-degradation ramp factor in[0.0, 1.0]for the given timing.booleangetSeed()inthashCode()static HttpChaosProfilebooleantimeWindowEligible(long firstMatchEpochMillis, long nowEpochMillis) Returnstruewhen the request falls within the time-based outage window defined byoutageAfterMillisandoutageDurationMillis, measured relative to the expectation's first match.withDegradationRampMillis(Long degradationRampMillis) withDropConnectionProbability(Double dropConnectionProbability) withErrorProbability(Double errorProbability) withErrorStatus(Integer errorStatus) withFailRequestCount(Integer failRequestCount) withGraphqlErrorCode(String graphqlErrorCode) withGraphqlErrorMessage(String graphqlErrorMessage) withGraphqlErrors(Boolean graphqlErrors) withGraphqlNullifyData(Boolean graphqlNullifyData) withLatency(Delay latency) withMalformedBody(Boolean malformedBody) withOutageAfterMillis(Long outageAfterMillis) withOutageDurationMillis(Long outageDurationMillis) withQuotaErrorStatus(Integer quotaErrorStatus) withQuotaLimit(Integer quotaLimit) withQuotaName(String quotaName) withQuotaWindowMillis(Long quotaWindowMillis) withRetryAfter(String retryAfter) withSlowResponseChunkDelay(Delay slowResponseChunkDelay) withSlowResponseChunkSize(Integer slowResponseChunkSize) withSucceedFirst(Integer succeedFirst) withTruncateBodyAtFraction(Double truncateBodyAtFraction) Methods inherited from class org.mockserver.model.ObjectWithJsonToString
toStringMethods inherited from class org.mockserver.model.ObjectWithReflectiveEqualsHashCodeToString
fieldsExcludedFromEqualsAndHashCode
-
Constructor Details
-
HttpChaosProfile
public HttpChaosProfile()
-
-
Method Details
-
httpChaosProfile
-
withErrorStatus
-
getErrorStatus
-
withRetryAfter
-
getRetryAfter
-
withErrorProbability
-
getErrorProbability
-
withDropConnectionProbability
-
getDropConnectionProbability
-
withLatency
-
getLatency
-
withSeed
-
getSeed
-
withSucceedFirst
-
getSucceedFirst
-
withFailRequestCount
-
getFailRequestCount
-
withOutageAfterMillis
-
getOutageAfterMillis
-
withOutageDurationMillis
-
getOutageDurationMillis
-
withTruncateBodyAtFraction
-
getTruncateBodyAtFraction
-
withMalformedBody
-
getMalformedBody
-
withSlowResponseChunkSize
-
getSlowResponseChunkSize
-
withSlowResponseChunkDelay
-
getSlowResponseChunkDelay
-
withQuotaName
-
getQuotaName
-
withQuotaLimit
-
getQuotaLimit
-
withQuotaWindowMillis
-
getQuotaWindowMillis
-
withQuotaErrorStatus
-
getQuotaErrorStatus
-
withDegradationRampMillis
-
getDegradationRampMillis
-
withGraphqlErrors
-
getGraphqlErrors
-
withGraphqlErrorMessage
-
getGraphqlErrorMessage
-
withGraphqlErrorCode
-
getGraphqlErrorCode
-
withGraphqlNullifyData
-
getGraphqlNullifyData
-
degradationFactor
public double degradationFactor(long firstMatchEpochMillis, long nowEpochMillis) Returns the gradual-degradation ramp factor in[0.0, 1.0]for the given timing. WhendegradationRampMillisisnullthere is no ramp and this returns1.0(faults at full configured rate). Otherwise the factor climbs linearly from0.0at the first match to1.0oncedegradationRampMillishas elapsed (and stays at1.0after). When the first-match instant is unknown (<= 0) the factor is1.0(degenerate — no ramp data, so do not suppress faults). The instants come from the controllable clock so the ramp is deterministic under clock freeze/advance.- Parameters:
firstMatchEpochMillis- epoch-ms of the expectation's first match (0 when not yet recorded)nowEpochMillis- the current epoch-ms (from the controllable clock)
-
copy
Returns a copy of this profile with all fields duplicated. Used to derive a transient, gradually-degraded variant without mutating the shared profile attached to the expectation. -
timeWindowEligible
public boolean timeWindowEligible(long firstMatchEpochMillis, long nowEpochMillis) Returnstruewhen the request falls within the time-based outage window defined byoutageAfterMillisandoutageDurationMillis, measured relative to the expectation's first match. When both fields arenullthere is no time gate and this returnstrue(backward compatible). The window opensoutageAfterMillisms after the first match and, whenoutageDurationMillisis set, closes (self-heals) after that duration. The instants are supplied by the controllable clock (TimeService) so the window is deterministic under clock freeze/advance.- Parameters:
firstMatchEpochMillis- epoch-ms of the expectation's first match (0 when not yet recorded)nowEpochMillis- the current epoch-ms (from the controllable clock)- Returns:
trueif this request is inside the outage window (or there is no window)
-
countWindowEligible
public boolean countWindowEligible(int matchCount) Returnstruewhen the given 1-based match count falls within the chaos-eligible window defined bysucceedFirstandfailRequestCount. When both fields arenullthis returnstruefor anymatchCount(backward compatible), includingmatchCount == 0which the handler passes when chaos is null (the no-chaos overloads).- Parameters:
matchCount- 1-based match count from the expectation (0 when unknown)- Returns:
trueif this match is eligible for chaos injection
-
equals
- Overrides:
equalsin classObjectWithReflectiveEqualsHashCodeToString
-
hashCode
public int hashCode()- Overrides:
hashCodein classObjectWithReflectiveEqualsHashCodeToString
-