Skip to main content

ADVANCED

Hooks and Lifecycle

Control test initialization, cleanup, and resource management using Karate's lifecycle hooks without requiring Java code.

On this page:

Hook Types Overview

HookWhen It RunsScope
karate-config.jsBefore every ScenarioGlobal
BackgroundBefore every Scenario in FeatureFeature
callonce in BackgroundOnce per FeatureFeature
karate.callSingle()Once globally (thread-safe)Global
configure afterScenarioAfter every ScenarioScenario
configure afterFeatureAfter all Scenarios in FeatureFeature

Background Setup

Use Background to run setup before every scenario in a feature:

Gherkin
Feature: User API tests

Background:
* url 'https://jsonplaceholder.typicode.com'
* def authToken = 'Bearer abc123'
* header Authorization = authToken

Scenario: Get user
Given path 'users', 1
When method get
Then status 200

Scenario: Get all users
Given path 'users'
When method get
Then status 200
And match response == '#[10]'

The Background runs before each scenario, ensuring consistent setup.

One-Time Feature Setup

Use callonce to execute expensive operations once per feature:

Gherkin
Feature: API tests with authentication

Background:
# Runs once per feature, cached for all scenarios
* def authData = callonce read('classpath:auth/login.feature')
* def token = authData.token
* url 'https://jsonplaceholder.typicode.com'
* header Authorization = 'Bearer ' + token

Scenario: First test
Given path 'users'
When method get
Then status 200

Scenario: Second test
Given path 'posts'
When method get
Then status 200
callonce vs call
  • call executes every time it's encountered
  • callonce executes once and caches the result for all scenarios in the feature

After Scenario Hook

Execute cleanup logic after each scenario:

Gherkin
Feature: After scenario cleanup

Background:
* configure afterScenario =
"""
function() {
karate.log('Scenario completed:', karate.scenario.name);
if (karate.info.errorMessage) {
karate.log('FAILED:', karate.info.errorMessage);
}
}
"""

Scenario: Test user endpoint
Given url 'https://jsonplaceholder.typicode.com'
And path 'users', 1
When method get
Then status 200

Available Properties in Hooks

Access scenario information within hooks:

PropertyDescription
karate.scenario.nameCurrent scenario name
karate.info.errorMessageError message if scenario failed (null if passed)
karate.info.scenarioTypeType: Scenario or Scenario Outline

After Feature Hook

Configure feature-level cleanup after all scenarios complete:

Gherkin
Feature: After feature cleanup

Background:
* configure afterFeature =
"""
function() {
karate.log('All scenarios in feature completed');
}
"""

Scenario: First scenario
* def result = 1 + 1
* match result == 2

Scenario: Second scenario
* def result = 2 + 2
* match result == 4
afterFeature Requirements

The afterFeature hook only works with the Runner API for parallel execution, not the JUnit runner.

// Required for afterFeature hooks to work
Results results = Runner.path("classpath:features").parallel(5);

After Scenario Outline Hook

Handle cleanup after all rows of a data-driven test complete:

Gherkin
Feature: Scenario Outline hooks

Background:
* configure afterScenario =
"""
function() {
karate.log('Row completed');
}
"""
* configure afterScenarioOutline =
"""
function() {
karate.log('All rows completed');
}
"""

Scenario Outline: Validate users
Given url 'https://jsonplaceholder.typicode.com'
And path 'users', <id>
When method get
Then status 200

Examples:
| id |
| 1 |
| 2 |
| 3 |
  • afterScenario runs after each Examples row
  • afterScenarioOutline runs once after all rows complete

Configuration File

karate-config.js

Configure global settings in karate-config.js (processed before every scenario):

karate-config.js
function fn() {
var env = karate.env || 'dev';
karate.log('Running in environment:', env);

var config = {
baseUrl: 'https://jsonplaceholder.typicode.com'
};

if (env === 'prod') {
config.baseUrl = 'https://api.production.com';
}

// Set timeouts globally
karate.configure('connectTimeout', 5000);
karate.configure('readTimeout', 5000);

return config;
}

Variables returned in config are available to all scenarios.

Environment-Specific Config

Create karate-config-<env>.js files to override settings per environment:

karate-config-dev.js
function fn() {
return {
baseUrl: 'http://localhost:8080',
debugMode: true
};
}

Run with: -Dkarate.env=dev

Global One-Time Setup

Use karate.callSingle() for initialization that runs once globally, even across parallel threads:

karate-config.js
function fn() {
var config = {
baseUrl: 'https://jsonplaceholder.typicode.com'
};

// Runs once globally, even in parallel execution
var auth = karate.callSingle('classpath:auth/get-token.feature');
config.authToken = auth.token;

return config;
}
callonce vs karate.callSingle()
  • callonce runs once per feature
  • karate.callSingle() runs once globally across all features, even in parallel

Multiple Cache Keys

Use different cache keys for different setups:

karate-config.js
function fn() {
var config = {};

// Different cache keys create separate cached results
var adminAuth = karate.callSingle('classpath:auth.feature?admin', {
username: 'admin',
password: 'admin123'
});

var userAuth = karate.callSingle('classpath:auth.feature?user', {
username: 'testuser',
password: 'user123'
});

config.adminToken = adminAuth.token;
config.userToken = userAuth.token;

return config;
}

The ?admin and ?user suffixes create separate cache entries.

Development Mode Caching

Cache authentication tokens to disk for faster development cycles:

karate-config.js
function fn() {
var config = {};

// Enable disk caching in dev mode
if (karate.env === 'dev') {
karate.configure('callSingleCache', { minutes: 15, dir: 'target/auth-cache' });
}

// This result will be cached to disk in dev mode
var auth = karate.callSingle('classpath:expensive-auth.feature');
config.authToken = auth.token;

return config;
}
Pure JSON Only

karate.callSingle() caching requires pure JSON return values. Avoid returning JavaScript functions or Java objects - they cause caching issues in parallel execution.

Hook Summary Table

To Run CodeHow
Before everything (globally once)karate.callSingle() in karate-config.js
Before every ScenarioBackground section or karate-config.js
Once per Featurecallonce in Background
After every Scenarioconfigure afterScenario
After every Scenario Outlineconfigure afterScenarioOutline
After all Scenarios in Featureconfigure afterFeature (requires Runner API)

Next Steps