call vs callonce for Auth Setup Reuse in Karate DSL
0 reputation · 27 Nov 2024, 17:35 UTC
0 reputation · 27 Nov 2024, 17:35 UTC
When structuring a Karate test suite that requires an authenticated session across multiple scenarios, the decision between call and callonce for the login feature directly affects test isolation, execution time, and token validity.
The authentication token returned by the setup feature has a fixed TTL (e.g., 15 minutes). The suite runs in parallel across multiple threads or Maven forks. callonce caches the result for the test run, but its cache scope — per JVM, per thread, or per fork — is version-dependent and not globally guaranteed. call in a Background re-executes the login per scenario, preserving isolation but increasing API calls and risking rate limits.
The team needs a single documented approach that works reliably across local runs, CI pipelines with forked test processes, and parallel threads without manual token refresh logic in every scenario.
callonce cache scope extend across forked JVMs in the same Maven/Gradle build, or is it confined to a single runner instance?callonce with a conditional re-authentication hook?34775 reputation · 27 Nov 2024, 19:24 UTC
In a Karate test suite that runs locally, in CI, and with Maven/Gradle forks, callonce caches per JVM/thread, not across Maven forks, so a single token isn’t reused automatically. call re‑executes the login for every scenario, guaranteeing a fresh token but increasing API traffic and risking rate‑limit throttling. The only way to get a single, shared token without duplicating login logic is to combine callonce with a conditional re‑authentication step that runs inside the same JVM (or test thread) and refreshes the token when the TTL expires.
callonce: per‑JVM, not across Maven/Gradle forks. Parallel threads inside the same JVM still see separate caches.callonce does not automatically refresh; you must add a check that re‑calls the login if the stored token is older than the TTL.Background to get the token once per JVM, then a background step that checks karate.get('authToken') and karate.get('authTokenTimestamp') and re‑calls the login if needed.callonce is scoped to the running process; no cross‑fork sharing is guaranteed.login.feature that returns the token and the timestamp.
Feature: Login
Scenario:
Given url 'https://api.example.com/auth/login'
And request { \"user\": \"alice\", \"pass\": \"secret\" }
When method post
Then status 200
And def token = response.token
And def ts = now
And set karate.env = { 'authToken': token, 'authTokenTs': ts }
And match response contains { token: '#string' }
Background use callonce to get the token once per JVM.
Background:
* def auth = callonce('classpath:login.feature')
* def authToken = auth.token
* def authTokenTs = auth.ts
* def now = now
* def elapsed = now - authTokenTs
* if (elapsed > 15 * 60 * 1000) {
* def newAuth = call('classpath:login.feature')
* def authToken = newAuth.token
* def authTokenTs = now
}
authToken in all subsequent requests via Authorization: Bearer ${authToken}.
forkCount>1 or Gradle’s maxParallelForks? If so, each fork will have its own callonce cache.callonce reduces the number of calls but you still need the refresh guard.
Could you confirm whether your test execution uses Maven Surefire/Gradle with multiple forks or simply parallel threads within a single JVM? Knowing the fork/parallel strategy will help fine‑tune the caching strategy.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.