HTTP REQUESTS
Polling and Async
Handle asynchronous operations with retry until - enabling robust polling for async APIs, job processing, and eventual consistency testing.
Benefits of Retry Until
- No manual loops: Built-in polling eliminates boilerplate retry code
- Declarative syntax: Express retry conditions as simple JavaScript expressions
- Configurable timing: Adjust retry count and intervals per scenario or globally
- Robust async testing: Handle eventual consistency and long-running operations reliably
Simple Retry Pattern
Wait for a condition with automatic retrying:
Scenario: Poll until job completes
* configure retry = { count: 10, interval: 2000 }
Given url baseUrl
And path 'jobs', jobId
And retry until response.status == 'completed'
When method get
Then status 200
And match response.result == '#object'
Key Points
- Default retry is 3 attempts with 3-second intervals
- Retry conditions must be pure JavaScript expressions
- Use
configure retry
to customize behavior
Retry with Multiple Conditions
Combine conditions using JavaScript operators:
Scenario: Wait for processing and validation
* configure retry = { count: 15, interval: 3000 }
Given url baseUrl
And path 'processing/status'
And retry until responseStatus == 200 && response.progress >= 100
When method get
Then status 200
And match response.status == 'success'
Retry with Data Validation
Wait for complex data conditions:
Scenario: Wait for aggregation completion
* configure retry = { count: 20, interval: 2000 }
Given url baseUrl
And path 'data/aggregation'
And param dataset = 'users'
And retry until responseStatus == 200 && response.totalRecords > 0
When method get
Then match response.totalRecords == '#number'
And match response.data == '#[]'
Retry Configuration
Customize retry behavior per scenario or environment:
Scenario: Environment-specific retry
* def env = karate.env || 'dev'
* def retryConfig = env == 'prod' ?
{ count: 30, interval: 5000 } : # Patient in prod
{ count: 10, interval: 1000 } # Fast in dev
* configure retry = retryConfig
Given url baseUrl
And path 'jobs', jobId
And retry until response.status != 'pending'
When method get
Then status 200
Job Processing Workflows
Handle async job lifecycle from submission to completion:
Scenario: Complete async job workflow
# Step 1: Submit job
Given url baseUrl
And path 'jobs/submit'
And request { type: 'image-processing', input: 'image.jpg' }
When method post
Then status 202
* def jobId = response.jobId
# Step 2: Poll for completion
* configure retry = { count: 30, interval: 2000 }
Given path 'jobs', jobId
And retry until response.status == 'completed'
When method get
Then status 200
And match response.result.outputUrl == '#string'
Event-Driven Testing
Test event-driven systems and webhooks:
Scenario: Wait for webhook delivery
* def webhookUrl = 'https://webhook.site/unique-id'
# Trigger action that sends webhook
Given url baseUrl
And path 'notifications/send'
And request { type: 'user-created', userId: 123, webhookUrl: '#(webhookUrl)' }
When method post
Then status 200
# Poll webhook endpoint for delivery
* configure retry = { count: 20, interval: 3000 }
Given url webhookUrl
And retry until response != null && response.type == 'user-created'
When method get
And match response.userId == 123
Error Handling with Retry
Handle multiple outcomes in retry conditions:
Scenario: Retry with error recovery
* configure retry = { count: 25, interval: 2000 }
Given url baseUrl
And path 'unstable/service'
And retry until responseStatus == 200 || responseStatus == 404
When method get
# Handle different outcomes
* if (responseStatus == 200) karate.log('Success')
* if (responseStatus == 404) karate.fail('Resource not found')
Advanced Retry Patterns
Custom retry logic with conditional handling:
Scenario: Retry until error resolved
* configure retry = { count: 20, interval: 1500 }
Given url baseUrl
And path 'eventually-consistent/endpoint'
And retry until responseStatus < 500
When method get
Then status 200
And match response.data == '#present'
Performance Considerations
- Long polling increases test execution time significantly
- Configure retry globally in
karate-config.js
for consistent behavior - Consider timeout settings when working with slow services
Next Steps
- Process async results: Response Handling
- Learn WebSocket and advanced patterns: Advanced Polling
- Configure request settings: Configuration