Virtual Service
While Specmatic’s service virtualization provides stateless API mocking capabilities, modern applications often requires data persistance for testing complex workflows. The virtual service feature was introduced to address this need, providing stateful behavior that mirrors real-world API interactions.
Key differences from service virtualization:
- Maintains state across requests
- Enables testing of complex workflows
- Supports scenarios requiring data persistence
- Allows validation of state-dependent business logic
This makes virtual-service particularly valuable for:
- Testing multi-step API workflows
- Validating state transitions
- Simulating real-world API behaviors
- Development without external service dependencies
Pre-requisites
- Create a directory named
specmatic
in your home directory. - Make sure you have installed Specmatic. Explore the Getting Started page for all options for installing Specmatic.
Example Usage
- Create a file named
employees.yaml
in thespecmatic
directory with the following contents.
openapi: 3.0.0
info:
title: Employees
version: '1.0'
paths:
/employees:
get:
summary: Get all employees
responses:
'200':
description: List of employees
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/EmployeeWithId'
post:
summary: Create a new employee
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Employee'
responses:
'201':
description: Employee created
content:
application/json:
schema:
$ref: '#/components/schemas/EmployeeWithId'
/employees/{id}:
get:
summary: Get a single employee by ID
parameters:
- name: id
in: path
required: true
schema:
type: integer
responses:
'200':
description: Employee details
content:
application/json:
schema:
$ref: '#/components/schemas/EmployeeWithId'
'404':
description: Employee not found
put:
summary: Update an existing employee
parameters:
- name: id
in: path
required: true
schema:
type: integer
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Employee'
responses:
'200':
description: Employee updated
content:
application/json:
schema:
$ref: '#/components/schemas/EmployeeWithId'
'404':
description: Employee not found
delete:
summary: Delete an employee
parameters:
- name: id
in: path
required: true
schema:
type: integer
responses:
'204':
description: Employee deleted
'404':
description: Employee not found
components:
schemas:
Employee:
type: object
required:
- name
- department
- designation
properties:
name:
type: string
department:
type: string
designation:
type: string
EmployeeWithId:
allOf:
- $ref: '#/components/schemas/Employee'
- type: object
required:
- id
properties:
id:
type: integer
- In the same directory, create a file named
specmatic.yaml
with the following contents:
version: 2
contracts:
- consumes:
- employees.yaml
cd
into thespecmatic
directory and run the following command:
-
java -jar specmatic.jar virtual-service
-
npx specmatic virtual-service
-
docker run -p 9000:9000 -v "${PWD}/:/usr/src/app" znsio/specmatic virtual-service
-
In a new tab, run the following curl command:
curl http://localhost:9000/employees
Here you will see an empty response
[]
which means there is no employees data at this moment. -
Now let’s try to create an employee using POST request, run the following curl command:
curl -X POST -H 'Content-Type: application/json' -d '{"name": "Jill Doe", "department": "Engineering", "designation": "Director"}' http://localhost:9000/employees
The employee will get created and you will see the following response:
{ "name": "Jill Doe", "department": "Engineering", "designation": "Director", "id": <ID> }
- Now run the previous curl command again to query all the employees using GET request,
curl http://localhost:9000/employees
and you will see an employee which was created previously using POST request in the response,
[ { "name": "Jill Doe", "department": "Engineering", "designation": "Director", "id": <ID> } ]
-
Now try to query the
<ID>
received in the previous command using curl:curl http://localhost:9000/employees/<ID>
and you will see below response,
{ "name": "Jill Doe", "department": "Engineering", "designation": "Director", "id": <ID> }
This shows how Specmatic’s virtual service maintains state across requests. Now you can do other CRUD operations using methods such as GET, POST, PUT, PATCH and DELETE etc.
Command Line Options
specmatic virtual-service [-hV] [--host=<host>] [--port=<port>] [--examples=<exampleDirectoryName>]
Option | Description |
---|---|
-h, --help |
Show help message and exit |
--host=<host> |
Host for the virtual service (default: localhost) |
--port=<port> |
Port for the virtual service (default: 9000) |
--examples=<exampleDirectoryName> |
Directories containing JSON examples for initial state |
-v, --version |
Print version information and exit |
Working with State
Default Behavior
The virtual service maintains state automatically based on your API specifications. For example:
- When you create a resource using a defined endpoint, it’s stored in the service’s state
- Subsequent requests will interact with the stored state according to your API specifications
- All operations defined in your contract specifications are supported with appropriate state management
Pre-loading State
You can initialize the service with pre-defined data:
-
By default, Specmatic looks for examples in a directory named
{specification-name}_examples
in the same location as your specification file. For instance, if your spec file is namedemployee_details.yaml
, Specmatic will look for examples in theemployees_examples
directory.-
Create the example in
employees_examples/example.json
,{ "http-request": { "method": "GET", "path": "/employees/10" }, "http-response": { "status": 200, "body": { "id": 10, "name": "Jamie Rivera", "department": "Engineering", "designation": "Senior Software Engineer" } } }
- Start the virtual service
specmatic virtual-service
- Make curl request to find all the employees using below command,
curl http://localhost:9000/employees
you will see the below response,
[ { "id": 10, "name": "Jamie Rivera", "department": "Engineering", "designation": "Senior Software Engineer" } ]
And that’s how you can pre-load / seed the data before starting the virtual service.
-
-
Custom directory name can be passed using
--examples
flag,specmatic virtual-service --examples="<customExampleDirectory>"
Specmatic also provides GUI for generating examples, checkout Interactive Examples GUI
Common Use Cases
Local Development / API Sandbox / API Playground
# Start service on a specific port
specmatic virtual-service --port=8080
This allows developers to work against a realistic API implementation without depending on external services.
Integration Testing / Ephemeral Environment Testing
# Start with pre-loaded test data
specmatic virtual-service --examples="spec_file_name_examples"
Perfect for integration tests that require consistent initial state.
API Design Validation
The virtual service helps validate API design decisions early by providing a working implementation that maintains state according to your specifications.
Troubleshooting
Common Issues
- Port Already in Use
# Solution: Use a different port specmatic virtual-service --port=9001
- Example Files Not Loading
- Verify JSON format is valid
- Check file permissions
- Ensure path to examples directory is correct
- Resource Not Found
- Make sure your API specification follows format similar to /resource and /resource/{id}.
- Sub-paths like /resource/add, /resource/delete/{id} are not allowed and will be ignored.