在 soapui/groovy 中断言时出现 Xpath 错误(传递响应 xml 在 groovy 方法中断言元素)
Xpath error while asserting in soapui/groovy ( pass response xml assert elements in groovy method)
我在脚本断言中有这个
def holder = new XmlHolder( messageExchange.responseContentAsXml )
持有人的价值是
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<ns0:SOME_SEARCHResponse xmlns:ns0="urn:AA:BBB:CCC:some_WS">
<ns0:some_ID>22222</ns0:Some_ID>
<ns0:some_ID>33333</ns0:Some_ID>
<ns0:Status>OK</ns0:Response>
...
...
下面是断言方法,在脚本库中
def assertions(xmlHolder, String... StringToAssert){
StringToAssert.each{
return xmlHolder.containsKey(StringToAssert)
}
}
我正在从脚本断言中调用如下断言方法
assert true==context.Change.assertions(holder,"//ns0:Some_ID")
但收到以下错误,我无法理解错误的来源。
net.sf.saxon.trans.XPathException: XPath syntax error at char 1 on line 2 in {\n[Ljava.lang.String}: Unexpected token "[" in path expression
编辑
@albciff 评论后的最终版本如下所示
def assertions(xmlHolder,String... stringToAssert){
def results = stringToAssert.collect{ element ->
return xmlHolder.containsKey(element)
}
return results.every{it==true}
//return results.contains(true)
}
问题出在您的断言函数定义中,因为您没有单独传递数组 StringToAssert
的每个元素,而是传递了整个数组。这就是你得到 Unexpected token "[" in path expression
的原因,因为在你的示例中 xmlHolder.containsKey
正在接收 ["//ns0:Some_ID"]
而不是 //ns0:Some_ID
,因此持有者试图从数组中评估 [
.
所以你必须纠正你的功能:
StringToAssert.each{
return xmlHolder.containsKey(StringToAssert)
}
类似于:
StringToAssert.each{ element ->
// now you pass the element of the array instead the whole array
return xmlHolder.containsKey(element)
}
或使用 collect
获取列表中的所有 containsKey
结果:
def results = StringToAssert.collect{ elem ->
return xmlHolder.containsKey(elem)
}
此外,您的代码中还有另一个问题。您的 XPath 不正确,在您的 xml <some_ID>
开始小写但是您的 XPath 不是 "//ns0:Some_ID"
并且因为在您的 XPath 中未定义 ns0
前缀,最好使用 *
通配符来匹配节点,所以最后你的 XPath 必须是 "//*:some_ID"
.
最后一个在您的断言中,您正在将 assertions
函数结果与 true
:
进行比较
assert true==context.Change.assertions(holder,"//ns0:Some_ID")
由于您的 assertions
函数没有 return 任何内容,默认情况下 groovy return 是您使用的最后一个对象,在这种情况下参数 stringToAssert
所以你真的在做类似的事情:
assert true==["//ns0:Some_ID"]
这就是您的断言失败的原因。因此,将 return 从 assertions
函数更改为
如果所有事情都得到纠正,代码可能如下所示:
import com.eviware.soapui.support.XmlHolder
def xml = '''<ns0:SOME_SEARCHResponse xmlns:ns0="urn:AA:BBB:CCC:some_WS">
<ns0:some_ID>22222</ns0:some_ID>
<ns0:some_ID>33333</ns0:some_ID>
<ns0:Status>OK</ns0:Status>
</ns0:SOME_SEARCHResponse>'''
def holder = new XmlHolder( xml )
def assertions(xmlHolder, String... stringToAssert){
// check if xmlHolder contains at least one
// element defined in the xpaths arrays
def results = stringToAssert.collect{ elem ->
return xmlHolder.containsKey(elem)
}
// if at least one xpath is satisfied returns true
return results.contains(true)
}
assert true==holder.containsKey('//*:some_ID')
希望对您有所帮助,
我在脚本断言中有这个
def holder = new XmlHolder( messageExchange.responseContentAsXml )
持有人的价值是
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<ns0:SOME_SEARCHResponse xmlns:ns0="urn:AA:BBB:CCC:some_WS">
<ns0:some_ID>22222</ns0:Some_ID>
<ns0:some_ID>33333</ns0:Some_ID>
<ns0:Status>OK</ns0:Response>
...
...
下面是断言方法,在脚本库中
def assertions(xmlHolder, String... StringToAssert){
StringToAssert.each{
return xmlHolder.containsKey(StringToAssert)
}
}
我正在从脚本断言中调用如下断言方法
assert true==context.Change.assertions(holder,"//ns0:Some_ID")
但收到以下错误,我无法理解错误的来源。
net.sf.saxon.trans.XPathException: XPath syntax error at char 1 on line 2 in {\n[Ljava.lang.String}: Unexpected token "[" in path expression
编辑 @albciff 评论后的最终版本如下所示
def assertions(xmlHolder,String... stringToAssert){
def results = stringToAssert.collect{ element ->
return xmlHolder.containsKey(element)
}
return results.every{it==true}
//return results.contains(true)
}
问题出在您的断言函数定义中,因为您没有单独传递数组 StringToAssert
的每个元素,而是传递了整个数组。这就是你得到 Unexpected token "[" in path expression
的原因,因为在你的示例中 xmlHolder.containsKey
正在接收 ["//ns0:Some_ID"]
而不是 //ns0:Some_ID
,因此持有者试图从数组中评估 [
.
所以你必须纠正你的功能:
StringToAssert.each{
return xmlHolder.containsKey(StringToAssert)
}
类似于:
StringToAssert.each{ element ->
// now you pass the element of the array instead the whole array
return xmlHolder.containsKey(element)
}
或使用 collect
获取列表中的所有 containsKey
结果:
def results = StringToAssert.collect{ elem ->
return xmlHolder.containsKey(elem)
}
此外,您的代码中还有另一个问题。您的 XPath 不正确,在您的 xml <some_ID>
开始小写但是您的 XPath 不是 "//ns0:Some_ID"
并且因为在您的 XPath 中未定义 ns0
前缀,最好使用 *
通配符来匹配节点,所以最后你的 XPath 必须是 "//*:some_ID"
.
最后一个在您的断言中,您正在将 assertions
函数结果与 true
:
assert true==context.Change.assertions(holder,"//ns0:Some_ID")
由于您的 assertions
函数没有 return 任何内容,默认情况下 groovy return 是您使用的最后一个对象,在这种情况下参数 stringToAssert
所以你真的在做类似的事情:
assert true==["//ns0:Some_ID"]
这就是您的断言失败的原因。因此,将 return 从 assertions
函数更改为
如果所有事情都得到纠正,代码可能如下所示:
import com.eviware.soapui.support.XmlHolder
def xml = '''<ns0:SOME_SEARCHResponse xmlns:ns0="urn:AA:BBB:CCC:some_WS">
<ns0:some_ID>22222</ns0:some_ID>
<ns0:some_ID>33333</ns0:some_ID>
<ns0:Status>OK</ns0:Status>
</ns0:SOME_SEARCHResponse>'''
def holder = new XmlHolder( xml )
def assertions(xmlHolder, String... stringToAssert){
// check if xmlHolder contains at least one
// element defined in the xpaths arrays
def results = stringToAssert.collect{ elem ->
return xmlHolder.containsKey(elem)
}
// if at least one xpath is satisfied returns true
return results.contains(true)
}
assert true==holder.containsKey('//*:some_ID')
希望对您有所帮助,