HTTP RESPONSES
Response Validation
Validate API responses using built-in match operations and schema validation markers—no custom assertion libraries or external dependencies required. Built-in type checking with fuzzy matchers (#number, #string, #array, #object), flexible matching modes (exact, partial, schema-based), and unified syntax for JSON, XML, and text responses.
On this page:
- Simple Response Validation - exact field and object matching
- Schema Validation - type markers and validation expressions
- Array Validation - size checks and
match each - Contains Operations - partial and order-independent matching
- Self-Validation Expressions - custom logic with
#? - File-Based Validation - compare against expected files
- Error Response Validation - validate error structures
Simple Response Validation
Validate JSON responses using exact match operations:
Feature: Basic JSON validation
Scenario: Match response fields
Given url 'https://jsonplaceholder.typicode.com'
And path 'users', 1
When method get
Then status 200
And match response.id == 1
And match response.name == 'Leanne Graham'
And match response.username == 'Bret'
Match entire response objects for exact validation:
Feature: Exact object matching
Scenario: Validate complete response structure
Given url 'https://jsonplaceholder.typicode.com'
And path 'posts', 1
When method get
Then status 200
And match response == { userId: 1, id: 1, title: '#string', body: '#string' }
Prefer match over assert for better error messages—match shows expected vs actual values when assertions fail. Use assert only for numeric comparisons (>, <, >=, <=).
Schema Validation
Use type markers to validate response structure without hardcoding values:
Feature: Type-based validation
Scenario: Validate with type markers
Given url 'https://jsonplaceholder.typicode.com'
And path 'users', 1
When method get
Then status 200
And match response ==
"""
{
id: '#number',
name: '#string',
username: '#string',
email: '#regex .+@.+',
phone: '#string',
website: '#string',
address: '#object',
company: '#object'
}
"""
Validation Markers Reference
| Marker | Description |
|---|---|
#ignore | Skip comparison for this field |
#null | Expects null value, key must be present |
#notnull | Expects non-null value |
#present | Key must be present (any value including null) |
#notpresent | Key must not exist |
#array | Expects JSON array |
#object | Expects JSON object |
#boolean | Expects boolean |
#number | Expects number |
#string | Expects string |
#uuid | Expects UUID format string |
#regex STR | Expects string matching regex pattern |
##type | Optional field (can be null or absent) |
Advanced Validation Markers
Combine type markers with validation expressions and optional fields:
Feature: Advanced schema validation
Scenario: Complex validation markers
Given url 'https://jsonplaceholder.typicode.com'
And path 'posts', 1
When method get
Then status 200
And match response ==
"""
{
userId: '#number? _ > 0',
id: '#number',
title: '#string? _.length > 0',
body: '#string'
}
"""
Use ## prefix for optional fields that may be null or absent. For example, ##string matches a string, null, or missing key.
Array Validation
Validate array size and content with flexible matching:
Feature: Array validation
Scenario: Array size and structure
Given url 'https://jsonplaceholder.typicode.com'
And path 'users'
When method get
Then status 200
And match response == '#[10]'
And match each response == { id: '#number', name: '#string', email: '#string' }
Array Size Syntax
Feature: Array size validation
Scenario: Validate array sizes
Given url 'https://jsonplaceholder.typicode.com'
And path 'posts'
And param userId = 1
When method get
Then status 200
# exact size
And match response == '#[10]'
# size with condition
And match response == '#[_ > 5]'
# array of specific type
And match response == '#[] #object'
Match Each for Array Elements
Validate every element in an array:
Feature: Match each validation
Scenario: Validate all array elements
Given url 'https://jsonplaceholder.typicode.com'
And path 'users'
When method get
Then status 200
And match each response == { id: '#number', name: '#string', email: '#regex .+@.+' }
And match each response contains { id: '#number' }
Contains Operations
Use contains for order-independent and partial matching:
Feature: Contains validation
Scenario: Partial matching
Given url 'https://jsonplaceholder.typicode.com'
And path 'users', 1
When method get
Then status 200
And match response contains { id: 1, username: 'Bret' }
And match response.address contains { city: 'Gwenborough' }
Contains Variants
Feature: Contains variants
Scenario: Different contains operations
Given url 'https://jsonplaceholder.typicode.com'
And path 'posts'
And param userId = 1
When method get
Then status 200
# contains - check if items exist (order doesn't matter)
And match response[*].id contains 1
And match response[*].id contains [1, 2, 3]
# contains any - at least one item matches
And match response[*].id contains any [1, 999, 888]
# karate.distinct() to get unique values for contains only
* def uniqueUserIds = karate.distinct(response[*].userId)
And match uniqueUserIds contains only [1]
Contains Deep
For nested structures, use contains deep to match recursively:
Feature: Deep contains
Scenario: Nested structure matching
Given url 'https://jsonplaceholder.typicode.com'
And path 'users', 1
When method get
Then status 200
And match response contains deep { address: { city: 'Gwenborough' } }
And match response contains deep { company: { name: 'Romaguera-Crona' } }
Not Contains
Verify that values are absent:
Feature: Not contains validation
Scenario: Verify absence
Given url 'https://jsonplaceholder.typicode.com'
And path 'users', 1
When method get
Then status 200
And match response !contains { error: '#notnull' }
And match response !contains { deleted: true }
Self-Validation Expressions
Use #? expressions for custom validation logic:
Feature: Self-validation expressions
Scenario: Custom validation logic
Given url 'https://jsonplaceholder.typicode.com'
And path 'users', 1
When method get
Then status 200
And match response.id == '#number? _ > 0'
And match response.name == '#string? _.length > 0'
And match response.email == '#string? _.includes("@")'
Cross-Field Validation
Reference other fields using $ for the JSON root:
Feature: Cross-field validation
Scenario: Validate related fields
* def data = { min: 10, max: 100, value: 50 }
* match data == { min: '#number', max: '#number', value: '#? _ >= $.min && _ <= $.max' }
Reusable Validation Functions
Define reusable validation functions for complex scenarios:
Feature: Reusable validators
Scenario: Custom validators
* def isValidEmail = function(email) { return email.includes('@') && email.includes('.') }
* def isPositive = function(n) { return n > 0 }
Given url 'https://jsonplaceholder.typicode.com'
And path 'users', 1
When method get
Then status 200
And match response.id == '#? isPositive(_)'
And match response.email == '#? isValidEmail(_)'
File-Based Validation
Compare responses against expected files for regression testing:
Feature: File-based validation
Background:
* def expectedUser = read('classpath:expected/user-schema.json')
Scenario: Compare to expected response
Given url 'https://jsonplaceholder.typicode.com'
And path 'users', 1
When method get
Then status 200
And match response == expectedUser
Use schema files for consistent validation across tests:
Feature: Schema file validation
Background:
* def postSchema = { userId: '#number', id: '#number', title: '#string', body: '#string' }
Scenario: Validate with reusable schema
Given url 'https://jsonplaceholder.typicode.com'
And path 'posts'
When method get
Then status 200
And match each response == postSchema
XML Response Validation
Validate XML responses using XPath expressions:
Feature: XML validation
Scenario: XPath validation
Given url 'https://httpbin.org'
And path 'xml'
When method get
Then status 200
And match /slideshow/@title == 'Sample Slide Show'
And match /slideshow/slide[1]/title == 'Wake up to WonderWidgets!'
Fuzzy matching markers work in XML as well:
Feature: XML fuzzy matching
Scenario: XML with type markers
* def xml = <user><id>123</id><name>John</name></user>
* match xml == <user><id>#string</id><name>#string</name></user>
* match xml/user/id == '#string'
Error Response Validation
Validate error responses with specific structure checks:
Feature: Error response validation
Scenario: Validate 404 response
Given url 'https://jsonplaceholder.typicode.com'
And path 'users', 99999
When method get
Then status 404
And match response == {}
Validate structured error responses:
Feature: Structured error validation
Scenario: Validate error structure
Given url 'https://httpbin.org'
And path 'status', 400
When method get
Then status 400
Conditional Validation
Apply different validation rules based on response content:
Feature: Conditional validation
Scenario: Validate based on content
Given url 'https://jsonplaceholder.typicode.com'
And path 'users', 1
When method get
Then status 200
* def hasCompany = response.company != null
* if (hasCompany) karate.match('response.company', { name: '#string', catchPhrase: '#string', bs: '#string' })
Next Steps
- Monitor API performance: Response Time
- Handle response data: Response Handling
- Learn advanced matching: Match Keyword