mockserver-client 7.1.0 → 7.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +173 -1
- data/lib/mockserver/a2a.rb +529 -0
- data/lib/mockserver/binary_launcher.rb +31 -1
- data/lib/mockserver/client.rb +815 -7
- data/lib/mockserver/forward_chain_expectation.rb +16 -6
- data/lib/mockserver/llm.rb +855 -0
- data/lib/mockserver/mcp.rb +453 -0
- data/lib/mockserver/models.rb +681 -11
- data/lib/mockserver/rspec.rb +56 -0
- data/lib/mockserver/version.rb +1 -1
- data/lib/mockserver-client.rb +3 -0
- metadata +6 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: fa28c69e849b63f6fa75a1f57f939a348cf30d3032d6b1dfb040276dbd51eb6b
|
|
4
|
+
data.tar.gz: 188c6469fc18b0ed51b4099a652d68a3b00b0bbccda233265b282e9d08e5c677
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c4d3d24b31236d09f8684b10bc114e6cb2154f532ff230453f9e3f566ecbd271ef4c770a8d3f6db6a2476bd89efdd529471ba4fb46ca2ebe0e89e8a97f2fc63e
|
|
7
|
+
data.tar.gz: daef70802e8ee57033d185f74c580c3b61d87eb97fc0c74ab31288f345e9fe86c9823b6ff6f90231d2066c8b9f05a6446d5ba06a7d917bdb61dd1215ef2094ae
|
data/README.md
CHANGED
|
@@ -99,6 +99,150 @@ All 25 domain model classes are available under the `MockServer` module:
|
|
|
99
99
|
- `Ports`
|
|
100
100
|
- `RequestDefinition` (alias for `HttpRequest`)
|
|
101
101
|
|
|
102
|
+
## LLM Mocking
|
|
103
|
+
|
|
104
|
+
Fluent builders under `MockServer::LLM` mock LLM provider endpoints. They produce
|
|
105
|
+
expectations whose action is carried in the `httpLlmResponse` field; MockServer
|
|
106
|
+
re-encodes the provider-agnostic completion into the configured provider's wire
|
|
107
|
+
shape (OpenAI / Anthropic / Gemini / Bedrock / ...) when serving the request.
|
|
108
|
+
|
|
109
|
+
```ruby
|
|
110
|
+
require 'mockserver-client'
|
|
111
|
+
|
|
112
|
+
client = MockServer::Client.new('localhost', 1080)
|
|
113
|
+
|
|
114
|
+
# A single completion mock
|
|
115
|
+
MockServer::LLM.llm_mock('/v1/chat/completions')
|
|
116
|
+
.with_provider(MockServer::LLM::Provider::OPENAI)
|
|
117
|
+
.with_model('gpt-4o')
|
|
118
|
+
.responding_with(
|
|
119
|
+
MockServer::LLM.completion
|
|
120
|
+
.with_text('Hello!')
|
|
121
|
+
.with_usage(MockServer::LLM.usage.with_input_tokens(10).with_output_tokens(5))
|
|
122
|
+
)
|
|
123
|
+
.apply_to(client)
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Multi-turn **conversations** use MockServer scenario-state advancement so each
|
|
127
|
+
turn is served once, in order. Add per-turn predicates with `when_*` methods and
|
|
128
|
+
optionally isolate per session with `isolate_by`:
|
|
129
|
+
|
|
130
|
+
```ruby
|
|
131
|
+
MockServer::LLM.conversation
|
|
132
|
+
.with_path('/v1/chat/completions')
|
|
133
|
+
.with_provider(MockServer::LLM::Provider::OPENAI)
|
|
134
|
+
.isolate_by(MockServer::LLM.header('x-session-id'))
|
|
135
|
+
.turn.when_latest_message_contains('weather')
|
|
136
|
+
.responding_with(MockServer::LLM.completion.with_text('It is sunny.'))
|
|
137
|
+
.turn.responding_with(MockServer::LLM.completion.with_text('Anything else?'))
|
|
138
|
+
.apply_to(client)
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
**Failover** scenarios script N upstream failures (consecutive identical failures
|
|
142
|
+
are coalesced) followed by a success; default JSON error bodies are generated per
|
|
143
|
+
status code unless a custom body is supplied:
|
|
144
|
+
|
|
145
|
+
```ruby
|
|
146
|
+
MockServer::LLM.llm_failover
|
|
147
|
+
.with_path('/v1/chat/completions')
|
|
148
|
+
.with_provider(MockServer::LLM::Provider::OPENAI)
|
|
149
|
+
.fail_with(429, 2) # two rate-limit failures
|
|
150
|
+
.fail_with(503) # then one service-unavailable
|
|
151
|
+
.then_respond_with(MockServer::LLM.completion.with_text('Recovered'))
|
|
152
|
+
.apply_to(client)
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Each builder also exposes `build` to obtain the raw expectation Hash(es) without
|
|
156
|
+
registering them.
|
|
157
|
+
|
|
158
|
+
## MCP Mocking
|
|
159
|
+
|
|
160
|
+
`MockServer::MCP.mcp_mock` builds the set of expectations needed to emulate a
|
|
161
|
+
Streamable-HTTP MCP (Model Context Protocol) server speaking JSON-RPC 2.0. It
|
|
162
|
+
generates `initialize`, `ping`, `notifications/initialized`, and per-capability
|
|
163
|
+
`tools`, `resources`, and `prompts` handlers.
|
|
164
|
+
|
|
165
|
+
```ruby
|
|
166
|
+
MockServer::MCP.mcp_mock('/mcp')
|
|
167
|
+
.with_server_name('MyServer')
|
|
168
|
+
.with_tool('get_weather')
|
|
169
|
+
.with_description('Get the weather for a city')
|
|
170
|
+
.with_input_schema('{"type":"object","properties":{"city":{"type":"string"}}}')
|
|
171
|
+
.responding_with('72F and sunny')
|
|
172
|
+
.and_then
|
|
173
|
+
.with_resource('file:///config.json')
|
|
174
|
+
.with_name('config')
|
|
175
|
+
.with_content('{"debug":true}')
|
|
176
|
+
.and_then
|
|
177
|
+
.with_prompt('greet')
|
|
178
|
+
.with_argument('name', 'who to greet', true)
|
|
179
|
+
.responding_with('user', 'Hello there')
|
|
180
|
+
.and_then
|
|
181
|
+
.apply_to(client)
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
`build` returns the raw expectation Hashes if you prefer to register them yourself.
|
|
185
|
+
|
|
186
|
+
## A2A Mocking
|
|
187
|
+
|
|
188
|
+
`MockServer::A2A.a2a_mock` builds the set of expectations needed to emulate an
|
|
189
|
+
A2A (Agent-to-Agent) agent: an agent card served at `/.well-known/agent.json`
|
|
190
|
+
plus JSON-RPC 2.0 `tasks/send`, `tasks/get`, and `tasks/cancel` over `POST
|
|
191
|
+
<path>`. It optionally adds SSE streaming, push-notification config + delivery,
|
|
192
|
+
per-message custom task handlers, and advertised skills.
|
|
193
|
+
|
|
194
|
+
```ruby
|
|
195
|
+
MockServer::A2A.a2a_mock('/a2a')
|
|
196
|
+
.with_agent_name('WeatherAgent')
|
|
197
|
+
.with_agent_description('Forecasts the weather')
|
|
198
|
+
.with_skill('weather')
|
|
199
|
+
.with_name('Weather lookup')
|
|
200
|
+
.with_tag('forecast')
|
|
201
|
+
.with_example('What is the weather in Paris?')
|
|
202
|
+
.and_then
|
|
203
|
+
.with_streaming
|
|
204
|
+
.with_push_notifications('http://localhost:1234/a2a/callback')
|
|
205
|
+
.on_task_send
|
|
206
|
+
.matching_message('forecast')
|
|
207
|
+
.responding_with('Sunny, 25C')
|
|
208
|
+
.and_then
|
|
209
|
+
.apply_to(client)
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
When push notifications are configured, each `tasks/send` both returns the
|
|
213
|
+
JSON-RPC task response to the caller *and* POSTs the completed task to the
|
|
214
|
+
webhook URL. As with MCP mocking, `build` returns the raw expectation Hashes if
|
|
215
|
+
you prefer to register them yourself.
|
|
216
|
+
|
|
217
|
+
## SRE Control Plane (SLO + Chaos)
|
|
218
|
+
|
|
219
|
+
Verify service-level objectives and drive scheduled chaos experiments against
|
|
220
|
+
the running MockServer:
|
|
221
|
+
|
|
222
|
+
```ruby
|
|
223
|
+
# Evaluate SLOs over a window. Returns the verdict Hash on PASS/INCONCLUSIVE;
|
|
224
|
+
# raises MockServer::VerificationError on FAIL (HTTP 406).
|
|
225
|
+
verdict = client.verify_slo(
|
|
226
|
+
'name' => 'checkout-latency',
|
|
227
|
+
'window' => 'PT5M',
|
|
228
|
+
'minimumSampleCount' => 100,
|
|
229
|
+
'objectives' => [
|
|
230
|
+
{ 'sli' => 'p99_latency_ms', 'comparator' => 'LESS_THAN', 'threshold' => 250 }
|
|
231
|
+
]
|
|
232
|
+
)
|
|
233
|
+
|
|
234
|
+
# Start a scheduled multi-stage chaos experiment (only one may be active).
|
|
235
|
+
client.start_chaos_experiment(
|
|
236
|
+
'name' => 'payments-brownout',
|
|
237
|
+
'stages' => [
|
|
238
|
+
{ 'durationMillis' => 60_000, 'profiles' => { 'payments.svc' => 'LATENCY' } }
|
|
239
|
+
]
|
|
240
|
+
)
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
SLO tracking must be enabled on the server (`sloTrackingEnabled=true`) or
|
|
244
|
+
`verify_slo` raises `MockServer::Error` on HTTP 400.
|
|
245
|
+
|
|
102
246
|
## Interactive Breakpoints
|
|
103
247
|
|
|
104
248
|
The client supports matcher-driven interactive breakpoints over the callback WebSocket. Register a breakpoint matcher to pause forwarded/proxied exchanges at specific phases and inspect/modify/continue them via callback handlers.
|
|
@@ -172,7 +316,7 @@ launcher_path = MockServer::BinaryLauncher.ensure_launcher
|
|
|
172
316
|
### Specify a version
|
|
173
317
|
|
|
174
318
|
```ruby
|
|
175
|
-
handle = MockServer::BinaryLauncher.start(port: 1080, version: '7.
|
|
319
|
+
handle = MockServer::BinaryLauncher.start(port: 1080, version: '7.3.0')
|
|
176
320
|
```
|
|
177
321
|
|
|
178
322
|
### API reference
|
|
@@ -203,6 +347,34 @@ handle = MockServer::BinaryLauncher.start(port: 1080, version: '7.1.0')
|
|
|
203
347
|
|
|
204
348
|
By default the launcher downloads the MockServer version matching this client gem (currently `MockServer::VERSION` from `lib/mockserver/version.rb`). Pass an explicit `version:` keyword to override.
|
|
205
349
|
|
|
350
|
+
## Using in tests (RSpec)
|
|
351
|
+
|
|
352
|
+
Require `mockserver/rspec` to get a shared context that provides a fresh
|
|
353
|
+
`MockServer::Client` per example and resets the server before and after each
|
|
354
|
+
example, so recorded requests, expectations and logs never leak between
|
|
355
|
+
examples:
|
|
356
|
+
|
|
357
|
+
```ruby
|
|
358
|
+
# spec_helper.rb
|
|
359
|
+
require 'mockserver/rspec'
|
|
360
|
+
|
|
361
|
+
# any spec tagged :mockserver gets a reset `mockserver` client
|
|
362
|
+
RSpec.describe 'my integration', :mockserver do
|
|
363
|
+
it 'records the request' do
|
|
364
|
+
# `mockserver` is the shared, reset client
|
|
365
|
+
mockserver.when(
|
|
366
|
+
MockServer::HttpRequest.request(path: '/hello')
|
|
367
|
+
).respond(
|
|
368
|
+
MockServer::HttpResponse.response(body: 'world', status_code: 200)
|
|
369
|
+
)
|
|
370
|
+
end
|
|
371
|
+
end
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
Host and port default to `127.0.0.1:1080` and can be overridden with the
|
|
375
|
+
`MOCKSERVER_HOST` / `MOCKSERVER_PORT` environment variables, or by defining a
|
|
376
|
+
`mockserver_host` / `mockserver_port` `let` in your example group.
|
|
377
|
+
|
|
206
378
|
## License
|
|
207
379
|
|
|
208
380
|
Apache-2.0
|