Initial upload: mockapi - OpenAPI Mock Server Generator
Some checks failed
CI / test (push) Has been cancelled
CI / build (push) Has been cancelled

This commit is contained in:
2026-03-22 21:06:26 +00:00
parent 147f5f9bc8
commit a4ac86a0eb

View File

@@ -0,0 +1,155 @@
"""Mock Server Generator using connexion."""
import random
from typing import Any, Dict, Optional
import connexion
from connexion import App, Resolution
from connexion.resolver import Resolver
from mockapi.core.config import Config
from mockapi.core.generators import DataGenerator
from mockapi.core.delay import DelayMiddleware
class MockOperationResolver(Resolver):
"""Custom operation resolver for mock API."""
def __init__(self, mock_server_generator):
"""Initialize the resolver.
Args:
mock_server_generator: The MockServerGenerator instance
"""
super().__init__()
self.mock_server_generator = mock_server_generator
def resolve(self, operation):
"""Resolve an operation to a mock function.
Args:
operation: The operation object from connexion
Returns:
Resolution object with the mock function
"""
operation_id = self.resolve_operation_id(operation)
for path, path_item in self.mock_server_generator.spec.get("paths", {}).items():
for method, op_def in path_item.items():
if method in ["get", "post", "put", "delete", "patch", "options", "head"]:
if op_def.get("operationId") == operation_id:
func = self.mock_server_generator._create_mock_function(op_def)
return Resolution(func, operation_id)
raise Exception(f"Operation {operation_id} not found")
class MockServerGenerator:
"""Generates a mock server from an OpenAPI specification."""
def __init__(self, spec: Dict[str, Any], config: Optional[Config] = None):
"""Initialize the mock server generator.
Args:
spec: The OpenAPI specification dictionary
config: Configuration object
"""
self.spec = spec
self.config = config or Config()
schemas = spec.get("components", {}).get("schemas", {})
self.data_generator = DataGenerator(seed=self.config.seed, schemas=schemas)
self.app: Optional[App] = None
def generate(self) -> App:
"""Generate the connexion application.
Returns:
Configured connexion App instance
"""
self.app = connexion.App(__name__, specification_dir=".")
self.app.add_api(
self.spec,
validate_responses=self.config.validate_responses,
strict_validation=self.config.strict_validation,
resolver=MockOperationResolver(self),
)
if self.config.delay > 0 or self.config.random_delay:
self.app = DelayMiddleware.wrap(
self.app,
delay=self.config.delay,
random_delay=self.config.random_delay,
)
return self.app
def _create_mock_function(self, operation: Dict[str, Any]):
"""Create a mock function for an operation.
Args:
operation: The OpenAPI operation definition
Returns:
Function that generates mock responses
"""
def mock_function(*args, **kwargs):
mock_config = operation.get("x-mock-config", {})
if self._should_return_error(mock_config):
return self._generate_error_response(mock_config)
response_schema = operation.get("responses", {}).get("200", {}).get(
"content", {}
).get("application/json", {}).get("schema")
if response_schema:
data = self.data_generator.generate(response_schema)
return data, 200
return {"message": "Mock response"}, 200
mock_function._mockapi_operation = operation
return mock_function
def _should_return_error(self, mock_config: Dict[str, Any]) -> bool:
"""Determine if we should return an error response.
Args:
mock_config: x-mock-config extension data
Returns:
True if error should be returned
"""
error_probability = mock_config.get("errorProbability", 0)
return random.random() < error_probability
def _generate_error_response(self, mock_config: Dict[str, Any]) -> tuple:
"""Generate an error response.
Args:
mock_config: x-mock-config extension data
Returns:
Tuple of (response_body, status_code)
"""
status_code = mock_config.get("errorCode", 500)
error_message = mock_config.get("errorMessage", "Mock error")
return {"error": error_message}, status_code
def create_mock_server(
spec: Dict[str, Any],
config: Optional[Config] = None,
) -> App:
"""Create a mock server from an OpenAPI spec.
Args:
spec: OpenAPI specification dictionary
config: Configuration object
Returns:
Configured connexion App
"""
generator = MockServerGenerator(spec, config)
return generator.generate()