Citrus 中 xml 个序列元素的验证匹配器
Validation matcher for xml sequence elements in Citrus
我对正确使用 Citrus 验证匹配器有疑问。在官方 XML 示例中,为 getTodoListResponse
定义了以下 XSD 架构 (TodoList.xsd):
<xs:element name="getTodoListResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="list">
<xs:complexType>
<xs:sequence>
<xs:element name="todoEntry" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="id" type="xs:string"/>
<xs:element name="title" type="xs:string"/>
<xs:element name="description" type="xs:string" minOccurs="0"/>
<xs:element name="attachment" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:element name="cid" type="xs:string"/>
<xs:element name="contentType" type="xs:string"/>
<xs:element name="data" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="done" type="xs:boolean" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
定义的验证匹配器如下所示 (templates/getTodoListResponse.xml):
<todo:getTodoListResponse xmlns:todo="http://citrusframework.org/samples/todolist">
<todo:list>
<todo:todoEntry>
<todo:id>@ignore@</todo:id>
<todo:title>${todoName}</todo:title>
<todo:description>${todoDescription}</todo:description>
</todo:todoEntry>
</todo:list>
</todo:getTodoListResponse>
但是当 运行 通过 mvn verify
多次测试时,结果 XML 中有多个 todoEntry 元素。为了检查结果中返回的 XML 元素的变量列表。因此检查将失败。
问题是,是否有办法通过 XML 验证匹配器 API.
表达这个动态列表
我得到了一个基于 groovy 验证器的有效解决方案,如下所示:
assert root.list.children().size() > 1
(getTodoListResponseValidator.groovy)
但我更愿意看到它通过 XML 验证工作。似乎有类似的东西叫做 @matchesXml(),但是从文档中我不清楚这是否适合所描述的用例。
提前致谢。
再见
马里奥
归根结底,这只是针对 todo-list 演示的设计糟糕的测试。集成测试应始终在被测应用程序的 well-known 状态下运行。并且测试应该始终为其他测试留下干净的状态。该特定样本违反了这些原则。
事实上,您提到的示例只是一个演示,因此并不是作为完全合格的真实示例编写的。从那以后,测试在多次执行时不起作用。
要解决此问题,我建议在 before-test 步骤中清除待办事项列表,以便您始终在空列表上操作。另一种可能性是使用 XPath 验证而不是比较完整的条目列表。例如,XPath 验证可以检查列表条目的数量是否大于零(就像您在 groovy 脚本中所做的那样)。
除此之外,您还可以编写一个 XPath 表达式,它只验证服务器返回的待办事项列表中的最后一个条目。类似的东西
<validate path="count(//todo:todoEntry)" value="@greaterThan(0)@" result-type="number"/>
<validate path="//todo:todoEntry[last()]/todo:title" value="${todoName}"></validate>
我对正确使用 Citrus 验证匹配器有疑问。在官方 XML 示例中,为 getTodoListResponse
定义了以下 XSD 架构 (TodoList.xsd):
<xs:element name="getTodoListResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="list">
<xs:complexType>
<xs:sequence>
<xs:element name="todoEntry" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="id" type="xs:string"/>
<xs:element name="title" type="xs:string"/>
<xs:element name="description" type="xs:string" minOccurs="0"/>
<xs:element name="attachment" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:element name="cid" type="xs:string"/>
<xs:element name="contentType" type="xs:string"/>
<xs:element name="data" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="done" type="xs:boolean" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
定义的验证匹配器如下所示 (templates/getTodoListResponse.xml):
<todo:getTodoListResponse xmlns:todo="http://citrusframework.org/samples/todolist">
<todo:list>
<todo:todoEntry>
<todo:id>@ignore@</todo:id>
<todo:title>${todoName}</todo:title>
<todo:description>${todoDescription}</todo:description>
</todo:todoEntry>
</todo:list>
</todo:getTodoListResponse>
但是当 运行 通过 mvn verify
多次测试时,结果 XML 中有多个 todoEntry 元素。为了检查结果中返回的 XML 元素的变量列表。因此检查将失败。
问题是,是否有办法通过 XML 验证匹配器 API.
表达这个动态列表我得到了一个基于 groovy 验证器的有效解决方案,如下所示:
assert root.list.children().size() > 1
(getTodoListResponseValidator.groovy)
但我更愿意看到它通过 XML 验证工作。似乎有类似的东西叫做 @matchesXml(),但是从文档中我不清楚这是否适合所描述的用例。
提前致谢。
再见 马里奥
归根结底,这只是针对 todo-list 演示的设计糟糕的测试。集成测试应始终在被测应用程序的 well-known 状态下运行。并且测试应该始终为其他测试留下干净的状态。该特定样本违反了这些原则。
事实上,您提到的示例只是一个演示,因此并不是作为完全合格的真实示例编写的。从那以后,测试在多次执行时不起作用。
要解决此问题,我建议在 before-test 步骤中清除待办事项列表,以便您始终在空列表上操作。另一种可能性是使用 XPath 验证而不是比较完整的条目列表。例如,XPath 验证可以检查列表条目的数量是否大于零(就像您在 groovy 脚本中所做的那样)。
除此之外,您还可以编写一个 XPath 表达式,它只验证服务器返回的待办事项列表中的最后一个条目。类似的东西
<validate path="count(//todo:todoEntry)" value="@greaterThan(0)@" result-type="number"/>
<validate path="//todo:todoEntry[last()]/todo:title" value="${todoName}"></validate>