You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何重构Karate测试以消除对Service B的重复调用?

问题描述

我有一个Karate测试用例,里面包含4次重复的Service B请求调用,以及1次Service A的请求调用。希望把这4次重复的Service B调用重构为更简洁的实现方式,原测试代码如下:

@BcomRetry
Feature: Message Routing u

  Background:
    * configure ssl = true
    * configure httpVersion = 'http2'
    * def servicebBaseUrls = ['http://localhost:28090', 'https://localhost:28091', 'http://localhost:28092', 'https://localhost:28093']
    * def serviceaBaseUrl = 'http://localhost:28081'
    * configure retry = { count: 100 }
  Scenario: Test7   
    * def serviceb1BaseUrl = karate.get('servicebBaseUrls[0]')
    * def serviceb2BaseUrl = karate.get('servicebBaseUrls[1]')
    * def serviceb3BaseUrl = karate.get('servicebBaseUrls[2]')
    * def serviceb4BaseUrl = karate.get('servicebBaseUrls[3]')    
    * def serviceaBaseUrl = karate.get('serviceaBaseUrl')
    * def requestBody = read('sba-local-policy/request.json')
    * def expectedResponse1 = read('sba-local-policy/test7EndpointLookupResponse.json')
     
    * url serviceb1BaseUrl
    Given path '/service-b/v1/id'
    When method get
    Then status 200
    And print response
    
    * url serviceb2BaseUrl
    Given path '/service-b/v1/id'
    When method get
    Then status 200
    And print response

    * url serviceb3BaseUrl
    Given path '/service-b/v1/id'
    When method get
    Then status 200
    And print response

    * url serviceb4BaseUrl
    Given path '/service-b/v1/id'
    When method get
    Then status 200
    And print response

    * url serviceaBaseUrl    
    Given path '/service-a/v1/testLoadbalancer'
    And header Accept = 'application/json; charset=utf-8'
    And header Content-Type = 'application/json; charset=utf-8'
    And request requestBody
    When method post
    Then status 200
    Then match response == expectedResponse1  
重构方案

方案1:用循环遍历URL列表(最简单直接)

直接利用已有的servicebBaseUrls数组,通过karate.forEach循环处理每个Service B的请求,省去单独定义每个URL变量的步骤,代码更简洁:

@BcomRetry
Feature: Message Routing u

  Background:
    * configure ssl = true
    * configure httpVersion = 'http2'
    * def servicebBaseUrls = ['http://localhost:28090', 'https://localhost:28091', 'http://localhost:28092', 'https://localhost:28093']
    * def serviceaBaseUrl = 'http://localhost:28081'
    * configure retry = { count: 100 }
  Scenario: Test7   
    * def requestBody = read('sba-local-policy/request.json')
    * def expectedResponse1 = read('sba-local-policy/test7EndpointLookupResponse.json')
     
    # 循环遍历所有Service B的URL,统一执行请求
    * karate.forEach(servicebBaseUrls, function(url) {
        url url
        Given path '/service-b/v1/id'
        When method get
        Then status 200
        And print response
      })

    * url serviceaBaseUrl    
    Given path '/service-a/v1/testLoadbalancer'
    And header Accept = 'application/json; charset=utf-8'
    And header Content-Type = 'application/json; charset=utf-8'
    And request requestBody
    When method post
    Then status 200
    And match response == expectedResponse1  

方案2:提取Service B请求为可重用Feature(适合复杂场景)

如果后续Service B的请求逻辑可能变化,或者需要在其他测试用例中复用,可以把Service B的请求单独抽成一个独立的Feature文件:

新建service-b-check.feature文件

Feature: 检查Service B接口

  Scenario: 调用Service B的/id接口
    * url __arg
    Given path '/service-b/v1/id'
    When method get
    Then status 200
    And print response

主测试用例中循环调用这个Feature

@BcomRetry
Feature: Message Routing u

  Background:
    * configure ssl = true
    * configure httpVersion = 'http2'
    * def servicebBaseUrls = ['http://localhost:28090', 'https://localhost:28091', 'http://localhost:28092', 'https://localhost:28093']
    * def serviceaBaseUrl = 'http://localhost:28081'
    * configure retry = { count: 100 }
  Scenario: Test7   
    * def requestBody = read('sba-local-policy/request.json')
    * def expectedResponse1 = read('sba-local-policy/test7EndpointLookupResponse.json')
     
    # 循环调用重用的Feature,传入每个URL
    * karate.forEach(servicebBaseUrls, function(url) {
        call read('service-b-check.feature') url
      })

    * url serviceaBaseUrl    
    Given path '/service-a/v1/testLoadbalancer'
    And header Accept = 'application/json; charset=utf-8'
    And header Content-Type = 'application/json; charset=utf-8'
    And request requestBody
    When method post
    Then status 200
    And match response == expectedResponse1  

额外优化点

  1. 原代码中单独定义serviceb1BaseUrl到serviceb4BaseUrl完全没必要,直接用数组索引或者循环处理即可,上面的方案已经去掉了这些冗余代码。
  2. 原代码中def serviceaBaseUrl = karate.get('serviceaBaseUrl')属于重复定义,可以直接使用Background里的serviceaBaseUrl变量。

内容的提问来源于stack exchange,提问作者Starbucks Admin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 18:05:18