如何解决跨Scenario调用子Schema定义变量时的未定义错误
当你用karate.call调用@validateCommonSchema这个Scenario时,被调用Scenario里定义的bicyclesSchema变量仅存在于它自身的执行上下文,不会自动传递到调用方的上下文。而你返回的PIMSchema里引用了##(bicyclesSchema),当调用方使用这个PIMSchema时,当前上下文找不到该变量,就会抛出未定义的错误。
下面提供几种可行的解决方式:
方法1:返回所有依赖的Schema变量
修改被调用的Scenario,最后返回一个包含所有需要复用的Schema的对象,调用方拿到后将所有变量定义到当前上下文:
@validateCommonSchema Scenario: validate the Common Schema * def accountSchema = """ { "displayName":'#string' } """ * def bicyclesSchema = """ { "status_Ext": '#string' } """ * def PIMSchema = """ { "PIM": { "bicycleExists": '#boolean', "totalDiscount":{ "amount": '#string' }, "bicycles": '#[] ##(bicyclesSchema)' } } """ # 最后返回包含所有Schema的对象 * return { accountSchema: accountSchema, bicyclesSchema: bicyclesSchema, PIMSchema: PIMSchema }
修改调用方代码,把所有返回的变量都定义到当前上下文:
@id=ValidateMainSchema Scenario: Validate the Main Schema * def reqPayloadFile = sharedPath + 'SchemaValidationTrial.json' * def reqPayload = read(reqPayloadFile) * def commonSchemaRef=karate.call(sharedPath+'PPPPartnerEventsActions.feature'+'@validateCommonSchema') * def accountMainSchema = commonSchemaRef.accountSchema * def bicyclesMainSchema = commonSchemaRef.bicyclesSchema * def PIMMainSchema = commonSchemaRef.PIMSchema * def MainSchema = """ { "accessedByMember": '#boolean', "account": '##(accountMainSchema)', "line": '##(PIMMainSchema)' } """ * match reqPayload == '##(MainSchema)'
这样调用方上下文就有了bicyclesMainSchema,PIMMainSchema里的引用就能正常解析。
方法2:内嵌子Schema到父Schema中
如果bicyclesSchema仅被PIMSchema依赖,可以直接把它的内容内嵌到PIMSchema里,避免依赖外部变量:
@validateCommonSchema Scenario: validate the Common Schema * def accountSchema = """ { "displayName":'#string' } """ * def PIMSchema = """ { "PIM": { "bicycleExists": '#boolean', "totalDiscount":{ "amount": '#string' }, "bicycles": '#[] { "status_Ext": "#string" }' } } """ * return { accountSchema: accountSchema, PIMSchema: PIMSchema }
这种方式让PIMSchema成为独立的Schema,调用方直接使用即可,不会出现变量未定义的问题。
方法3:使用公共背景定义全局Schema
如果这些Schema需要在多个Scenario中复用,更推荐把它们定义在.feature文件的Background里,或者单独的公共Schema文件中,用karate.callSingle加载,这样所有Scenario都能直接访问:
创建CommonSchemas.feature:
Feature: Common Schema Definitions Background: * def accountSchema = """ { "displayName":'#string' } """ * def bicyclesSchema = """ { "status_Ext": '#string' } """ * def PIMSchema = """ { "PIM": { "bicycleExists": '#boolean', "totalDiscount":{ "amount": '#string' }, "bicycles": '#[] ##(bicyclesSchema)' } } """
在需要的Scenario里加载这个文件:
@id=ValidateMainSchema Scenario: Validate the Main Schema * def reqPayloadFile = sharedPath + 'SchemaValidationTrial.json' * def reqPayload = read(reqPayloadFile) # 加载公共Schema,所有变量会进入当前上下文 * karate.callSingle(sharedPath+'CommonSchemas.feature') * def MainSchema = """ { "accessedByMember": '#boolean', "account": '##(accountSchema)', "line": '##(PIMSchema)' } """ * match reqPayload == '##(MainSchema)'
karate.callSingle只会加载一次,是Karate中复用公共逻辑的最佳实践之一。
内容的提问来源于stack exchange,提问作者THOKCHOM PREMJIT

