Java xmlunit:ElementSelectors.conditionalBuilder出错
因此,我有以下输入、预期输出和实际输出xml: input.xml 当我运行上述输入并与expected-output.xml进行比较时,我得到了以下差异:Java xmlunit:ElementSelectors.conditionalBuilder出错,java,xml,xmlunit,xmlunit-2,Java,Xml,Xmlunit,Xmlunit 2,因此,我有以下输入、预期输出和实际输出xml: input.xml 当我运行上述输入并与expected-output.xml进行比较时,我得到了以下差异: [期望的子对象]{http://test.org/standards/intake}RqUID'但为'null'-将/ProductRq[1]/SvcRq[1]/NotificationRq[1]/RqUID[1]与(不同)进行比较,应为子项'null',但为'{http://test.org/standards/intake}RqUID'
[期望的子对象]{http://test.org/standards/intake}RqUID'但为'null'-将/ProductRq[1]/SvcRq[1]/NotificationRq[1]/RqUID[1]与(不同)进行比较,应为子项'null',但为'{http://test.org/standards/intake}RqUID'-与at/ProductRq[1]/SvcRq[1]/NotificationRq[1]/RqUID[1](不同)相比
我不明白为什么我的元素选择器不能工作,我是否使用错误?我的目标是,每当找到TransmissionId或NotificationRq/RqUID时,只通过名称将它们与预期的输出版本相匹配,否则对其他元素使用名称和文本,因为这些元素包含唯一生成的ID,这些ID会更改每个测试运行,并且无法预测(为了以后创建更复杂的选择器,例如,在名称空间添加到名称和属性时通过名称和属性比较ProductRq)。我是否缺少一些东西,我是否能够将两个XPath选择器组合在一起,而不是将几个when/then行和默认情况组合在一起
注意:xml是通过xslt转换的。PRoductRq上的名称空间不在源文档中;源文件被复制,名称空间被添加到PRoductRq中,然后与一些元素删除/修改/添加一起发送以供输出。XMLUnit表示
通知RQ
中的RqUID
元素与当然他们是不同的
.whenElementIsNamed("NotificationRq")
.thenUse(ElementSelectors.byXPath("./RqUID", ElementSelectors.byName))
意思是:当XMLUnit试图为NotificationRq
元素查找合作伙伴时,它必须搜索具有RqUID
子元素的NotificationRq
,并且只使用RqUID
元素
它不为任何其他元素设置任何规则,特别是RqUID
本身。对于RqUID
元素,默认规则适用,并且
.elseUse(ElementSelectors.byNameAndText)
表示:如果两个元素的名称和嵌套的文本匹配,XMLUnit只接受两个元素作为成对元素。这与所讨论的RqUID
元素不同
您的整个元素选择器
显示
- 匹配
s,如果它们具有任意内容的Audit
子级TransID
- 匹配
s,如果它们具有任意内容的NotificationRq
RqUID
- 否则,请使用元素名称和嵌套文本
- 通过元素名和嵌套文本匹配几乎所有内容(尽管从示例中可以看出,元素名就足够了)
- 忽略
的子级TransId
s的嵌套文本Audit
- 忽略
NotificationRq
foo
没有内置谓词。如果它是名为bar
的元素的子元素,则可能类似于
Predicate<Element> transIdInAudit = e -> {
if (e == null || e.getParentNode() == null) {
return false;
}
return "TransID".equals(e.getLocalName()) && "Audit".equals(e.getParentNode().getLocalName());
};
如果它们有匹配的RqUID
,可能您真的想匹配SvcRq
,可能不想。如果是这样,您会使用当前用于通知rq
的结构
这本身不足以忽略匹配的TransId
和RqUID
元素的嵌套文本,它只会确保XMLUnit选择您希望它使用的节点。对于嵌套文本,您需要一个DifferenceEvaluator
假设您使用的是元素选择器。默认情况下,ByName和Text
对于所有匹配的节点,嵌套的文本都是相同的,除了要忽略内容的两个特定元素。因此DifferenceEvaluator
类似于
DifferenceEvaluators.chain(DifferenceEvaluators.Default,
DifferenceEvaluators.downgradeDifferencesToEqual(ComparisonType.TEXT_VALUE))
应该可以工作。很好的解释,我想我误解了byXPath元素选择器,我认为这是按照这样的思路:如果元素名为this,那么将这个子元素与提供的选择器匹配,而不是它必须只使用带有默认规则的RqUID。我最终实现了2 DifferenceEvaluator,找到了一个解决方案但是这更干净
.whenElementIsNamed("NotificationRq")
.thenUse(ElementSelectors.byXPath("./RqUID", ElementSelectors.byName))
.elseUse(ElementSelectors.byNameAndText)
Predicate<Element> transIdInAudit = e -> {
if (e == null || e.getParentNode() == null) {
return false;
}
return "TransID".equals(e.getLocalName()) && "Audit".equals(e.getParentNode().getLocalName());
};
.withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.conditionalBuilder()
.when(transIdInAudit)
.thenUse(ElementSelectors.byName)
.when(rqUIDInNotificationRq) // similar to transIdInAudit
.thenUse(ElementSelectors.byName)
.elseUse(ElementSelectors.byNameAndText)
.build())
DifferenceEvaluators.chain(DifferenceEvaluators.Default,
DifferenceEvaluators.downgradeDifferencesToEqual(ComparisonType.TEXT_VALUE))