- Skill ID
- petrkindlmann/qa-skills/service-virtualization
- Publisher
- petrkindlmann
- Repository
- qa-skills
- Installs
- 0
- Files
- 7
- License
- MIT
- Synced
- Sep 23, 2026
Open any RiverX project, open the Skills panel in the chat, and search for this identifier. The files are fetched from the source repository at install time.
petrkindlmann/qa-skills/service-virtualizationInstalls these files- SKILL.md
- references/ci.md
- references/msw.md
- references/record-replay.md
- references/testcontainers.md
- references/toxiproxy.md
- references/wiremock.md
What this skill tells the agent
<objective> Mock Stripe at the SDK layer and your tests pass green while production 500s the moment Stripe changes a response field — because the stub was never tied to a contract. This skill picks the right isolation strategy per dependency (in-process mock, HTTP stub, record-replay, fault injection, or ephemeral real service), stubs at the HTTP layer so tests survive SDK upgrades, and makes the CI run fail when any real call escapes the stubs. </objective>
Quick Route
| Situation | Go to |
|---|---|
| Node/browser test hitting an external HTTP API | MSW → references/msw.md |
| Polyglot CI, complex matching, or you need a standalone stub server | WireMock → references/wiremock.md |
| Dependency is a DB / cache / queue | Testcontainers → references/testcontainers.md |
| Testing timeouts, latency, connection resets | Toxiproxy → references/toxiproxy.md |
| Bootstrapping stubs from a real API, or a multi-step baseline | Record-replay → references/record-replay.md |
| Wiring any of these into GitHub Actions | references/ci.md |
| Not sure which to reach for | Decision Tree (below) |
Discovery Questions
Check .agents/qa-project-context.md first — if it exists, use it, respect existing mocking conventions, and skip anything answered there. Then:
- How many external dependencies does the system call, and which are painful in tests? Rate-limited, slow, flaky, or paid dependencies are the highest-priority virtualization candidates; list payment, email, auth, and third-party data sources.
- What testing levels need isolation? Unit tests want fast in-process mocks; integration tests want HTTP-level stubs; E2E wants real or containerized services — the level sets the strategy.
- Does the provider offer an official test mode or sandbox? Stripe test mode, Twilio test creds, etc. beat any home-grown stub for fidelity — prefer them where they exist.
- Do you have contracts with these dependencies? If yes, contract tests keep stubs in sync; see
contract-testing. If no, mocking what you don't own is a known risk (Core Principle 3). - Docker available in CI? No Docker steers you to MSW (in-process); Docker unlocks WireMock, Testcontainers, and Toxiproxy.
Core Principles
1. Match the isolation level to the confidence you need. Unit tests can mock aggressively — they test internal logic. Integration tests should use realistic stubs or real services because they test boundaries. E2E should run the closest thing to production that is still reliable.
2. Real services beat fakes when they're fast, free, and reliable. A local PostgreSQL container gives more confidence than a fake and costs little — prefer it. Reserve fakes for dependencies that are slow, unreliable, or paid.
3. Never mock what you don't own without a contract — and prefer the provider's test mode. If you stub Stripe and Stripe changes its response shape, your tests stay green while production breaks. In order of preference: use the provider's official test mode/sandbox (Stripe test mode, Twilio test creds) → an HTTP stub validated by a contract test for drift → a bare stub only when nothing better exists. See contract-testing.
4. Stubs must fail realistically. A stub that always returns 200 never exercises error handling. Every stub needs error variants: 429 rate limits, 500s, timeouts, malformed bodies.
5. One abstraction layer between test and tool. Wrap MSW handlers, WireMock stubs, and Testcontainers setup behind a consistent interface so switching tools doesn't mean rewriting tests.
Decision Framework
When to use each isolation strategy
| Strategy | Speed | Fidelity | Complexity | Best for |
|---|---|---|---|---|
| In-process mock | Fastest | Lowest | Trivial | Unit tests, isolating internal modules |
| HTTP stub (MSW) | Fast | Medium | Low | Frontend/Node tests hitting external APIs |
| HTTP stub (WireMock) | Fast | Medium-High | Medium | Language-agnostic, complex matching rules |
| Record-replay | Fast after first run | High initially, decays | Medium | Bootstrapping stubs from real APIs quickly |
| Service fake | Medium | High | High | Stateful dependencies (in-memory DB, fake auth) |
| Ephemeral real (Testcontainers) | Slower | Highest | Medium | Databases, message queues, caches |
| Shared real service | Slow | Production-level | Low (to set up) | Staging validation, final pre-deploy check |
Decision tree
Is the dependency internal to your codebase?
├─ Yes → In-process mock (vi.mock / jest.mock / monkeypatch)
└─ No → Is it a database, cache, or message queue?
├─ Yes → Testcontainers (ephemeral real instance)
└─ No → Is it a third-party HTTP API?
├─ Yes → Does the provider offer a test/sandbox mode?
│ ├─ Yes → Use sandbox in staging, MSW/WireMock in CI
│ └─ No → MSW or WireMock + contract test for drift detection
└─ No → Is it an internal microservice?
├─ Yes → Contract test (Pact) + stub for consumer tests
└─ No → Evaluate case by caseTools
Pick MSW as the default for in-process Node/browser tests; WireMock for cross-language CI or standalone stub servers; Prism when the OpenAPI spec is the contract; Mockoon for dev-time exploratory mocking. Heavy code for each lives in references/ — pointers below.
MSW (Mock Service Worker)
MSW 2.x intercepts HTTP at the network layer (Service Worker in the browser, request interception in Node). The default for JS/TS projects. Stub at the HTTP layer (POST /v1/payment_intents), never at the SDK method — that decouples the test from the SDK version.
The strongest enforcement seam this skill offers: setupServer(...).listen({ onUnhandledRequest }). Set it to "error" in CI so any escaped real call fails the run; "warn" is fine locally while iterating.
See references/msw.md for centralized stateful handlers (payments), the Vitest setup with the CI/local onUnhandledRequest switch, per-test timeout/retry overrides, and a full stateful auth flow (create / verify / refresh / revoke via `http.delete`) keyed on a Bearer token.
WireMock
Language-agnostic HTTP stub server (current stable 3.13.2 — 4.0 is beta-only as of mid-2026, stay on 3.x for CI). Runs standalone or as a Docker container. Best for polyglot environments or complex matching rules.
Use priority-based mappings for error scenarios: a priority: 1 mapping that matches an opt-in header (X-Test-Scenario: rate-limit) and returns 429 shadows the default happy-path mapping only when the test asks for it. WireMock also exposes an admin API for programmatic stub creation (POST /__admin/mappings), verification (POST /__admin/requests/count), and reset (POST /__admin/mappings/reset).
See references/wiremock.md for the Docker setup, a response-templated paginated mapping, the priority error mapping JSON, and the drift-detection seam to contract-testing (replay a Pact or validate the stub against the OpenAPI spec via Prism).
Other HTTP mock servers
| Tool | Strengths | When to use |
|---|---|---|
| Mockoon | Desktop UI + CLI; OpenAPI import; rule-based responses; lightweight | Dev-time mocking and quick CLI mocks in CI |
| Hoverfly | Capture-replay (record real traffic, replay deterministically); capture/simulate/modify/synthesize modes | Migrating from a real dependency to a mock — record once, replay forever |
| Prism | OpenAPI-driven mock server (Stoplight); validates requests + generates responses from spec | OpenAPI-first projects with a published spec |
| MockServer | Java-based; rich expectation matching; multi-protocol | JVM teams already on MockServer |
Testcontainers
More from petrkindlmann
Use this skill in a project
Open any RiverX project, search the Skills panel for petrkindlmann/qa-skills/service-virtualization, and install it in one click.
