Dynamic Data
MockForge provides powerful dynamic data generation capabilities through its templating system and faker integration. This guide covers generating realistic, varied responses for comprehensive API testing and development.
Template Expansion Basics
MockForge uses a lightweight templating system with {{token}} syntax to inject dynamic values into responses.
Enabling Templates
Templates are disabled by default for security. Enable them using:
# Environment variable
MOCKFORGE_RESPONSE_TEMPLATE_EXPAND=true mockforge serve --spec api-spec.json
# Configuration file
http:
response_template_expand: true
Basic Template Syntax
paths:
/users:
get:
responses:
'200':
content:
application/json:
example:
users:
- id: "{{uuid}}"
name: "{{faker.name}}"
email: "{{faker.email}}"
created_at: "{{now}}"
Time-Based Templates
Generate timestamps and time offsets for realistic temporal data.
Current Time
responses:
'200':
content:
application/json:
example:
current_time: "{{now}}"
server_timestamp: "{{now}}"
Time Offsets
responses:
'200':
content:
application/json:
example:
created_at: "{{now-7d}}"
expires_at: "{{now+1h}}"
last_login: "{{now-30m}}"
scheduled_for: "{{now+2h}}"
Supported units:
s- secondsm- minutesh- hoursd- days
Random Data Generation
Generate random values for varied test data.
Random Integers
responses:
'200':
content:
application/json:
example:
user_count: "{{randInt 1 100}}"
age: "{{randInt 18 80}}"
score: "{{randInt -10 10}}"
Random Floats
responses:
'200':
content:
application/json:
example:
price: "{{randFloat 9.99 999.99}}"
rating: "{{randFloat 1.0 5.0}}"
percentage: "{{randFloat 0.0 100.0}}"
UUID Generation
Generate unique identifiers for entities.
responses:
'200':
content:
application/json:
example:
id: "{{uuid}}"
order_id: "{{uuid}}"
transaction_id: "{{uuid}}"
Faker Data Generation
Generate realistic fake data using the Faker library.
Basic Faker Functions
responses:
'200':
content:
application/json:
example:
user:
id: "{{uuid}}"
name: "{{faker.name}}"
email: "{{faker.email}}"
created_at: "{{now}}"
Extended Faker Functions
When the data-faker feature is enabled, additional functions are available:
responses:
'200':
content:
application/json:
example:
user:
name: "{{faker.name}}"
email: "{{faker.email}}"
phone: "{{faker.phone}}"
address: "{{faker.address}}"
company: "{{faker.company}}"
product:
name: "{{faker.word}}"
description: "{{faker.sentence}}"
color: "{{faker.color}}"
url: "{{faker.url}}"
ip_address: "{{faker.ip}}"
Disabling Faker
For deterministic testing, disable faker tokens:
MOCKFORGE_FAKE_TOKENS=false mockforge serve --spec api-spec.json
Request Data Access
Access data from incoming requests to create dynamic responses.
Path Parameters
paths:
/users/{userId}:
get:
parameters:
- name: userId
in: path
required: true
schema:
type: string
responses:
'200':
content:
application/json:
example:
id: "{{request.path.userId}}"
name: "User {{request.path.userId}}"
retrieved_at: "{{now}}"
Query Parameters
paths:
/users:
get:
parameters:
- name: limit
in: query
schema:
type: integer
default: 10
- name: format
in: query
schema:
type: string
enum: [brief, detailed]
responses:
'200':
content:
application/json:
example: |
{{#if (eq request.query.format 'detailed')}}
{
"users": [
{
"id": "{{uuid}}",
"name": "{{faker.name}}",
"email": "{{faker.email}}",
"profile": {
"bio": "{{faker.sentence}}",
"location": "{{faker.address}}"
}
}
],
"limit": {{request.query.limit}},
"format": "{{request.query.format}}"
}
{{else}}
{
"users": [
{
"id": "{{uuid}}",
"name": "{{faker.name}}",
"email": "{{faker.email}}"
}
],
"limit": {{request.query.limit}}
}
{{/if}}
Request Body Access
paths:
/users:
post:
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
name:
type: string
email:
type: string
responses:
'201':
content:
application/json:
example:
id: "{{uuid}}"
name: "{{request.body.name}}"
email: "{{request.body.email}}"
created_at: "{{now}}"
welcome_message: "Welcome {{request.body.name}}!"
Headers Access
responses:
'200':
content:
application/json:
example:
user_agent: "{{request.header.User-Agent}}"
api_version: "{{request.header.X-API-Version}}"
authorization: "{{request.header.Authorization}}"
Conditional Templates
Use Handlebars-style conditionals for complex logic.
Basic Conditionals
responses:
'200':
content:
application/json:
example: |
{{#if (eq request.query.format 'detailed')}}
{
"data": {
"id": "{{uuid}}",
"name": "{{faker.name}}",
"details": {
"bio": "{{faker.paragraph}}",
"stats": {
"login_count": {{randInt 1 1000}},
"last_active": "{{now-1d}}"
}
}
}
}
{{else}}
{
"data": {
"id": "{{uuid}}",
"name": "{{faker.name}}"
}
}
{{/if}}
Multiple Conditions
responses:
'200':
content:
application/json:
example: |
{{#if (eq request.query.type 'admin')}}
{
"user": {
"id": "{{uuid}}",
"name": "{{faker.name}}",
"role": "admin",
"permissions": ["read", "write", "delete", "admin"]
}
}
{{else if (eq request.query.type 'premium')}}
{
"user": {
"id": "{{uuid}}",
"name": "{{faker.name}}",
"role": "premium",
"permissions": ["read", "write"]
}
}
{{else}}
{
"user": {
"id": "{{uuid}}",
"name": "{{faker.name}}",
"role": "basic",
"permissions": ["read"]
}
}
{{/if}}
Data Generation Templates
MockForge includes built-in data generation templates for common entities.
User Template
# Generate user data
mockforge data template user --rows 10 --format json
# Output:
[
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "john.doe@example.com",
"name": "John Doe",
"created_at": "2024-01-15T10:30:00Z",
"active": true
}
]
Product Template
# Generate product data
mockforge data template product --rows 5 --format csv
# Output:
id,name,description,price,category,in_stock
550e8400-e29b-41d4-a716-446655440001,Wireless Headphones,High-quality wireless headphones with noise cancellation,199.99,Electronics,true
Order Template
# Generate order data with relationships
mockforge data template order --rows 3 --format json --rag
# Output:
[
{
"id": "550e8400-e29b-41d4-a716-446655440002",
"user_id": "550e8400-e29b-41d4-a716-446655440000",
"total_amount": 299.97,
"status": "completed",
"created_at": "2024-01-16T14:20:00Z"
}
]
Advanced Templating Features
Encryption Functions
Secure sensitive data in responses:
responses:
'200':
content:
application/json:
example:
user:
id: "{{uuid}}"
name: "{{encrypt 'user_name' faker.name}}"
email: "{{encrypt 'user_email' faker.email}}"
ssn: "{{encrypt 'sensitive' '123-45-6789'}}"
Decryption
Access encrypted data:
# In templates that need to decrypt
decrypted_name: "{{decrypt 'user_name' request.body.encrypted_name}}"
File System Access
Read external files for dynamic content:
responses:
'200':
content:
application/json:
example:
config: "{{fs.readFile 'config.json'}}"
template: "{{fs.readFile 'templates/welcome.html'}}"
Request Chaining Context
Access data from previous requests in chained scenarios.
Chain Variables
# In chained request templates
responses:
'200':
content:
application/json:
example:
previous_request_id: "{{chain.request_id}}"
previous_user_id: "{{chain.user.id}}"
session_token: "{{chain.auth.token}}"
Custom Template Plugins
Extend templating with custom functions via plugins.
Template Plugin Example
#![allow(unused)] fn main() { use mockforge_plugin_core::*; pub struct BusinessTemplatePlugin; impl TemplatePlugin for BusinessTemplatePlugin { fn execute_function( &mut self, function_name: &str, args: &[TemplateArg], _context: &PluginContext, ) -> PluginResult<String> { match function_name { "business_id" => { let id = format!("BIZ-{:010}", rand::random::<u32>()); PluginResult::success(id, 0) } "department" => { let depts = ["Engineering", "Sales", "Marketing", "HR"]; let dept = depts[rand::random::<usize>() % depts.len()]; PluginResult::success(dept.to_string(), 0) } "salary" => { let salary = rand::random::<u32>() % 150000 + 50000; PluginResult::success(salary.to_string(), 0) } _ => PluginResult::failure( format!("Unknown function: {}", function_name), 0 ) } } fn get_available_functions(&self) -> Vec<TemplateFunction> { vec![ TemplateFunction { name: "business_id".to_string(), description: "Generate business ID".to_string(), args: vec![], return_type: "string".to_string(), }, TemplateFunction { name: "department".to_string(), description: "Generate department name".to_string(), args: vec![], return_type: "string".to_string(), }, TemplateFunction { name: "salary".to_string(), description: "Generate salary amount".to_string(), args: vec![], return_type: "string".to_string(), }, ] } fn get_capabilities(&self) -> PluginCapabilities { PluginCapabilities::default() } fn health_check(&self) -> PluginHealth { PluginHealth::healthy("Business template plugin healthy".to_string(), PluginMetrics::default()) } } }
Using Custom Templates
responses:
'200':
content:
application/json:
example:
employee:
id: "{{business_id}}"
name: "{{faker.name}}"
department: "{{department}}"
salary: "{{salary}}"
hire_date: "{{now-1y}}"
Configuration and Security
Template Security Settings
# mockforge.yaml
http:
response_template_expand: true
template_security:
allow_file_access: false
allow_encryption: true
max_template_depth: 10
timeout_ms: 5000
Environment Variables
# Enable template expansion
MOCKFORGE_RESPONSE_TEMPLATE_EXPAND=true
# Disable faker for deterministic tests
MOCKFORGE_FAKE_TOKENS=false
# Set validation status for template errors
MOCKFORGE_VALIDATION_STATUS=422
# Control template execution timeout
MOCKFORGE_TEMPLATE_TIMEOUT_MS=5000
Testing with Dynamic Data
Manual Testing
# Test template expansion
curl http://localhost:3000/users
# Test with query parameters
curl "http://localhost:3000/users?format=detailed&limit=5"
# Test path parameters
curl http://localhost:3000/users/123
# Test POST with body access
curl -X POST http://localhost:3000/users \
-H "Content-Type: application/json" \
-d '{"name": "Test User", "email": "test@example.com"}'
Automated Testing
#!/bin/bash
# test-dynamic-data.sh
BASE_URL="http://localhost:3000"
echo "Testing dynamic data generation..."
# Test basic templates
USER_RESPONSE=$(curl -s $BASE_URL/users)
echo "User response with templates:"
echo $USER_RESPONSE | jq '.'
# Test conditional templates
DETAILED_RESPONSE=$(curl -s "$BASE_URL/users?format=detailed")
echo "Detailed format response:"
echo $DETAILED_RESPONSE | jq '.'
BASIC_RESPONSE=$(curl -s "$BASE_URL/users?format=basic")
echo "Basic format response:"
echo $BASIC_RESPONSE | jq '.'
# Test faker data
PRODUCT_RESPONSE=$(curl -s $BASE_URL/products)
echo "Product response with faker data:"
echo $PRODUCT_RESPONSE | jq '.'
echo "Dynamic data tests completed!"
Best Practices
Template Usage
- Enable Selectively: Only enable template expansion where needed for security
- Validate Input: Sanitize request data used in templates
- Test Thoroughly: Test template expansion with various inputs
- Monitor Performance: Templates add processing overhead
Data Generation
- Use Appropriate Faker: Choose faker functions that match your domain
- Maintain Consistency: Use consistent data patterns across endpoints
- Consider Relationships: Generate related data that makes sense together
- Balance Realism: Generate realistic but not sensitive data
Security Considerations
- Input Sanitization: Never trust request data in templates
- File Access: Disable file system access in production if not needed
- Encryption: Use encryption functions for sensitive data
- Rate Limiting: Consider rate limiting for expensive template operations
Performance Optimization
- Cache Static Parts: Cache template parsing for frequently used templates
- Limit Complexity: Avoid deeply nested conditionals and complex logic
- Profile Execution: Monitor template execution time and optimize slow functions
- Use Appropriate Timeouts: Set reasonable timeouts for template execution
Troubleshooting
Template Not Expanding
Problem: Templates appear as literal text in responses
Solutions:
# Enable template expansion
MOCKFORGE_RESPONSE_TEMPLATE_EXPAND=true mockforge serve --spec api-spec.json
# Check configuration
# Ensure response_template_expand: true in config
Faker Functions Not Working
Problem: Faker functions return empty or error values
Solutions:
# Ensure faker is enabled
MOCKFORGE_FAKE_TOKENS=true mockforge serve --spec api-spec.json
# Check if data-faker feature is enabled
# For extended faker functions, ensure the feature is compiled in
Request Data Access Issues
Problem: request.* variables are empty or undefined
Solutions:
- Verify request format (JSON for body access)
- Check parameter names match exactly
- Ensure path/query parameters are properly defined in OpenAPI spec
Performance Issues
Problem: Template expansion is slow
Solutions:
- Simplify template logic
- Cache frequently used values
- Use static responses where dynamic data isn’t needed
- Profile and optimize custom template functions
For basic HTTP mocking features, see the HTTP Mocking guide. For custom response generation, see the Custom Responses guide.