karatelabs/karate

karate.set(callSingle()) + call read() in Background freezes Outline row values

クローズ

#2,934 opened on 2026/06/19

 (1 件のコメント) (0 件のリアクション) (0 人の担当者)Java (1,893 件のフォーク)batch import
bughelp wanted

Repository metrics

Stars
 (7,600 個のスター)
PR merge metrics
 (平均マージ 1d 20h) (30d で 11 merged PRs)

説明

Description

When a Scenario Outline Background uses karate.set(karate.callSingle('feature')) followed by call read('feature'), all Outline rows receive row 1's Examples column values. The scope is frozen after row 1 — subsequent rows don't get their own values applied to #() expressions in the request body.

Observation- karate.set(callSingle()) followed by any call read() (with or without HTTP call) in Background seems to be the trigger. Neither alone triggers the issue — it's the combination.

Impact- The scope freeze affects BOTH the #() expressions in request bodies AND the variable references in assertions. Tests may false-pass because both the sent data and the expected values are frozen to row 1's values (Alice == Alice passes for all rows). The reproduction uses __num to reliably detect the freeze.

Steps to Reproduce

  1. Create a feature file using the snippets below.
Feature: karate.set(callSingle()) + call read() in Background freezes Outline row values

  Background:
    * karate.set( karate.callSingle('classpath:v2MigrationBugs/callSingleSetOutlineRows/constants.feature') )

    * def bgResult = call read('classpath:v2MigrationBugs/callSingleSetOutlineRows/bgNoHttpCall.feature')
    * def existingItems = bgResult.items || []

  Scenario Outline: Row <rowNum> - each row must have its own phoneNumber
    * def expectedPhones = ['1111111111', '2222222222', '3333333333', '4444444444']
    * def expectedPhone = expectedPhones[__num]

    # This assertion WILL FAIL on rows 2-4 if scope is frozen:
    # phone will be '1111111111' (row 1's value) but expectedPhone will differ
    * match phone == expectedPhone

    Examples:
    | fName!    | lName!   | phone!       | active! | rowNum! |
    | 'Alice'   | 'Smith'  | '1111111111' | true    | 1       |
    | 'Bob'     | 'Jones'  | '2222222222' | false   | 2       |
    | 'Charlie' | 'Brown'  | '3333333333' | true    | 3       |
    | 'Diana'   | 'Prince' | '4444444444' | false   | 4       |
  1. Create a feature file using the snippets below for constants.feature being called in the above feature from callSingle
@ignore
Feature: Simulated Pre-req (callSingle-cached, returns object for karate.set)

  Scenario:
    * def serviceName = 'TestService'
    * def baseUrl = 'https://httpbin.org'
    * def domainPath = '/anything'
    * def someFlag = true
    * def headers = { 'Content-Type': 'application/json' }
  1. Create a feature file using the snippets below for call read('feature') being called in the main feature's background.
@ignore
Feature: Background call WITHOUT HTTP (control test)

  Scenario:
    * def items = [{ id: 'item1' }, { id: 'item2' }]

Expected Behavior

  1. Each Scenario Outline row gets its own Examples column values. The Background re-executes for each row, and #(fName), #(lName), #(phone) in the request doc-string resolve to the current row's values. Each HTTP request contains distinct data.

Actual Behavior

  1. All rows receive row 1's values. The #() expressions in the doc-string resolve to row 1's column values for every subsequent row

Karate Version

2.1.0

Java Version

25.0.2

Operating System

macOS

コントリビューターガイド