Skip to main content

HTTP RESPONSES

Response Validation

Validate API responses using built-in match operations and schema validation markers—no custom assertion libraries or external dependencies required.

Benefits of Response Validation

  • Built-in type checking: Validate data types with fuzzy matchers like #number, #string, #array, #object
  • Flexible matching: Choose exact match, partial match, or schema-based validation
  • Cross-format support: JSON, XML, and text responses with unified syntax

Simple Response Validation

Validate JSON responses using exact match operations:

Feature: Basic JSON validation

Scenario: Match response fields
Given url baseUrl
And path 'users', 123
When method get
Then status 200
And match response.id == 123
And match response.name == 'John Doe'
And match response.active == true

Match entire response objects for exact validation:

Feature: Exact object matching

Scenario: Validate complete response structure
Given url baseUrl
And path 'users', 123
When method get
Then status 200
And match response == { id: 123, name: 'John Doe', active: true }

Schema Validation

Use type markers to validate response structure without hardcoding values:

Feature: Type-based validation

Scenario: Validate with type markers
Given url baseUrl
And path 'users', 123
When method get
Then status 200
And match response == {
id: '#number',
name: '#string',
email: '#regex .+@.+',
active: '#boolean',
created: '#string'
}

Advanced Validation Markers

Combine type markers with custom validation expressions and optional fields:

Feature: Advanced schema validation

Scenario: Complex validation markers
Given url baseUrl
And path 'api/user-profile'
When method get
Then status 200
And match response == {
id: '#uuid',
score: '#number? _ > 0',
status: '#regex (active|inactive)',
tags: '#[3] #string',
optionalField: '##string',
ignored: '#ignore',
requiredField: '#present'
}
Key Points
  • Use # prefix for type markers: #number, #string, #array, #object
  • Use ## prefix for optional fields that may be null or absent
  • Combine markers with validation: #number? _ > 0 validates positive numbers
  • Use #ignore to skip validation for specific fields

Array Validation

Validate array size and content with flexible matching:

Feature: Array validation

Scenario: Array size and structure
Given url baseUrl
And path 'users'
When method get
Then status 200
And match response.users == '#[10]'
And match response.users == '#[_ > 5]'
And match each response.users == { id: '#number', name: '#string', active: '#boolean' }

Validate nested arrays and cross-field validation:

Feature: Complex array validation

Scenario: Nested array validation
Given url baseUrl
And path 'api/orders'
When method get
Then status 200
And match each response.orders contains deep {
items: [{ product: '#string', price: '#number' }]
}
And match each response.orders contains {
total: '#? _ > 0'
}

XML Response Validation

Validate XML responses using XPath expressions:

Feature: XML validation

Scenario: XPath validation
Given url baseUrl
And path 'soap/users'
And request <getUserRequest><id>123</id></getUserRequest>
When soap action 'GetUser'
Then status 200
And match response/user/id == '123'
And match response/user/name == 'John Doe'
And match response == <user><id>123</id><name>John Doe</name></user>

Contains Operations

Use contains for order-independent and partial matching:

Feature: Contains validation

Scenario: Partial matching
Given url baseUrl
And path 'api/search'
And param query = 'laptop'
When method get
Then status 200
And match response.results contains { id: 123, name: 'Gaming Laptop' }
And match response.categoryIds contains [1, 3, 5]
And match response !contains { error: '#notnull' }

Advanced Contains Operations

Feature: Advanced contains operations

Scenario: Contains only and any
Given url baseUrl
And path 'api/products'
When method get
Then status 200
And match response.featured contains only [
{ id: 1, name: 'Product A' },
{ id: 2, name: 'Product B' }
]
And match response.categories contains any ['electronics', 'books', 'clothing']
And match response.products contains deep {
metadata: { tags: ['popular'] }
}

Self-Validation Expressions

Use #? expressions for custom validation logic and cross-field validation:

Feature: Self-validation expressions

Scenario: Custom validation logic
Given url baseUrl
And path 'api/financial-data'
When method get
Then status 200
And match response == {
temperature: {
celsius: '#number',
fahrenheit: '#? _ == $.celsius * 1.8 + 32'
},
date: {
month: '#number? _ > 0 && _ <= 12',
day: '#number? _ > 0 && _ <= 31',
year: '#number? _ > 2020'
},
price: '#number? _ > 0',
email: '#string? _.includes("@")'
}

Define reusable validation functions for complex scenarios:

Feature: Reusable validation functions

Scenario: Custom validators
* def isValidEmail = function(email) { return email.includes('@') && email.includes('.') }
* def isValidPrice = function(price) { return price > 0 && price < 10000 }

Given url baseUrl
And path 'api/user-profile'
When method get
Then status 200
And match response == {
email: '#? isValidEmail(_)',
subscriptionPrice: '#? isValidPrice(_)',
registrationDate: '#? new Date(_).getTime() > 0'
}

File-Based Validation

Compare responses against expected files for regression testing:

Feature: File-based validation

Scenario: Compare to expected response
Given url baseUrl
And path 'api/users', 123
When method get
Then status 200
And match response == read('expected-user-123.json')
And match response.profile == read('expected-user-profile.json')

Use file-based schemas for consistent validation:

Feature: Schema file validation

Scenario: Validate with schema file
Given url baseUrl
And path 'api/products'
When method get
Then status 200
* def productSchema = read('product-schema.json')
And match each response.products == productSchema

Conditional Validation

Apply different validation rules based on environment or context:

Feature: Conditional validation

Scenario: Environment-specific validation
* def env = karate.env || 'dev'

Given url baseUrl
And path 'api/config'
When method get
Then status 200

* if (env == 'prod')
"""
* match response.debugMode == false
* match response.logLevel == 'WARN'
* match response.features contains only ['core', 'stable']
"""
* if (env == 'dev')
"""
* match response.debugMode == true
* match response.logLevel == 'DEBUG'
* match response.features contains 'experimental'
"""

Error Response Validation

Validate error responses with specific structure and field checks:

Feature: Error response validation

Scenario: Validate error responses
Given url baseUrl
And path 'users', 99999
When method get
Then status 404
And match response == {
error: {
code: 'USER_NOT_FOUND',
message: '#string',
details: '##object'
},
timestamp: '#string',
path: '/users/99999'
}

Scenario: Validation error handling
Given url baseUrl
And path 'users'
And request { name: '', email: 'invalid-email' }
When method post
Then status 400
And match response == {
error: 'VALIDATION_ERROR',
message: '#string',
fields: '#[] { field: "#string", message: "#string" }'
}
And match response.fields[*].field contains ['name', 'email']
Validation Best Practices
  • Prefer match over assert for better error messages showing expected vs actual
  • Use contains for order-independent array validation
  • Use ## prefix for optional fields to handle null or absent values gracefully
  • JSON keys and string values are case-sensitive

Next Steps

Master response validation and continue with: