Migrating from XMLUnit 1.x to 2.x - xmlunit/user-guide GitHub Wiki
Part of XMLUnit for Java is a legacy
module which contains the
XMLUnit 1.x classes but reimplements most of the logic using the
XMLUnit 2.x engine. Using xmlunit-legacy
is the fastest way to
migrate but it is deprecated and will not be extended. New features
will only become available in xmlunit-core
or xmlunit-matchers
.
- XMLUnit 2.x will never try to compare unmatched nodes with arbitrary other nodes.
- XMLUnit 2.x will never care for the order of attributes.
- By default element order is significant in 2.x - use a custom
ElementSelector
if you wantSIMILAR
results for documents that differ in element order. The default of XMLUnit 1.x'sDiff
andDetailedDiff
translates toElementSelectors.byName
. - XMLUnit 2.x detects differences inside of the document's prolog - XMLUnit 1.x only cared for the doctype declaration. You can mimic this behavior by
chain
ingDifferenceEvaluators.ignorePrologDifferencesExceptDoctype
with theDifferenceEvaluator
you intended to use (most likelyDifferenceEvaluators.Default
.
XMLUnit 2.x has completely removed all static configuration.
XMLUnit 1.x | XMLUnit 2.x |
---|---|
XMLUnit.setIgnoreAttributeOrder() |
Attribute order is always ignored. |
XMLUnit.setCompareUnmatched() |
Unmatched nodes are never compared to other nodes. |
XMLUnit.setIgnoreComments() |
wrap the input in a CommentLessSource or use DiffBuilder.ignoreComments()
|
XMLUnit.setIgnoreDiffBetweenTextAndCDATA() |
TEXT and CDATA are considered ComparisonResult.SIMILAR (any other behaviour would require a custom DifferenceEvaluator ) |
XMLUnit.setIgnoreWhitespace() |
wrap the input in a WhitespaceStrippedSource or use DiffBuilder.ignoreWhitespace()
|
XMLUnit.setNormalizeWhitespace() |
wrap the input in a WhitespaceNormalizedSource or use DiffBuilder.normalizeWhitespace()
|
public void testXMLLegacyIdentical()throws Exception {
String myControlXML =
"<struct><int>3</int><boolean>false</boolean></struct>";
String myTestXML =
"<struct><boolean>false</boolean><int>3</int></struct>";
Diff myDiff = new Diff(myControlXML, myTestXML);
assertTrue("XML similar " + myDiff.toString(),
myDiff.similar());
assertTrue("XML identical " + myDiff.toString(),
myDiff.identical());
}
public void testXMLCoreIdentical()throws Exception {
String myControlXML =
"<struct><int>3</int><boolean>false</boolean></struct>";
String myTestXML =
"<struct><boolean>false</boolean><int>3</int></struct>";
Diff myDiffSimilar = DiffBuilder.compare(myControlXML).withTest(myTestXML)
.withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byName))
.checkForSimilar()
.build();
assertFalse("XML similar " + myDiffSimilar.toString(), myDiffSimilar.hasDifferences());
Diff myDiffIdentical = DiffBuilder.compare(myControlXML).withTest(myTestXML)
.withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byName))
.checkForIdentical()
.build();
assertFalse("XML identical " + myDiffIdentical.toString(), myDiffIdentical.hasDifferences());
}
public void testXMLMatchersIdentical()throws Exception {
String myControlXML =
"<struct><int>3</int><boolean>false</boolean></struct>";
String myTestXML =
"<struct><boolean>false</boolean><int>3</int></struct>";
assertThat(myTestXML, CompareMatcher.isSimilarTo(myControlXML));
assertThat(myTestXML, CompareMatcher.isIdenticalTo(myControlXML));
}
Where XMLUnit 1.x defaults to match elements by name, XMLUnit 2.x defaults to match elements in order. The .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byName))
line above is needed to mimic the default behaviour of 1.x.
In XmlUnit 2.x there is no DetailedDiff
anymore. The new Diff
object already contains all differences by default.
Old code:
DetailedDiff myDiff = new DetailedDiff(new Diff(myControlXML, myTestXML));
List allDifferences = myDiff.getAllDifferences();
assertEquals(myDiff.toString(), 2, allDifferences.size());
New Code
Diff myDiff = DiffBuilder.compare(myControlXML).withTest(myTestXML).build();
Iterable<Difference> differences = myDiff.getDifferences();
for (Difference difference : differences) {
System.out.println(difference);
}
In XMLUnit 1.x the use of Diff
implied the comparison would stop as
soon as the first real difference was found and you had to use
DetailedDiff
in order to find all differences.
With XMLUnit 2.x the decision to stop or continue the comparison
process is made by an instance of ComparisonController
(actually
XMLUnit 1.x uses DifferenceListener
for this and Diff
as well as
DetailedDiff
implement this).
If you want stop comparision after first difference found, you must
set a ComparisonController
:
DiffBuilder.withComparisonController(ComparisonControllers.StopWhenDifferent)
The old DifferenceListener
interface...
public interface DifferenceListener {
...
int differenceFound(Difference difference);
...
}
...is replaced by the new DifferenceEvaluator
interface:
public interface DifferenceEvaluator {
ComparisonResult evaluate(Comparison comparison, ComparisonResult outcome);
}
and its role is restricted to changing the severity of a comparison's
outcome. Unlike DifferenceListener
the new interface doesn't
influence whether the comparison process stops - this is the
responsibility of the new ComparisonController
interface.
XMLUnit 1.x | XMLUnit 2.x |
---|---|
difference.getControlNodeDetail().getNode() |
comparison.getControlDetails().getTarget() |
difference.getControlNodeDetail().getValue() |
comparison.getControlDetails().getValue() |
difference.getControlNodeDetail().getXpathLocation() |
comparison.getControlDetails().getXPath() |
difference.getTestNodeDetail() |
comparison.getTestDetails() |
difference.getDescription() |
responsibility of a ComparisionFormatter , e.g: new DefaultComparisonFormatter().getDescription(comparison)
|
difference.isRecoverable() |
you now get the ComparisonResult enum as separate paramter. If you need check for ComparisonResult.SIMILAR , you must chain your DifferenceEvaluator with the default evaluator (see example below). |
difference.getId() |
is now an enum: comparison.getType()
|
With XMLUnit 2.x you can chain multiple DifferenceEvaluators
:
DifferenceEvaluator chainedEvaluator = DifferenceEvaluators.chain(
DifferenceEvaluators.Default, new MyDifferenceEvaluator());
DifferenceEvaluators.chain()
will pass the outcome from one
evaluator to the next evaluator. In this example the
MyDifferenceEvaluator
can also check if the previous outcome was
ComparisonResult.SIMILAR
.
In XMLUnit 2.x the role of the old ElementQualifier
has been
expanded to the more general NodeMatcher
. Its default
implementation DefaultNodeMatcher
delegates part of its
responsibility to ElementSelector
and the easiest approach to
migrate an ElementQualifier
is to implement ElementSelector
and
use something like
NodeMatcher nodeMatcher = new DefaultNodeMatcher(new MyElementSelector()):
The Interfaces of the old ElementQualifier
and the new
ElementSelector
are very similar:
ElementQualifier
boolean qualifyForComparison(Element control, Element test);
ElementSelector
boolean canBeCompared(Element controlElement, Element testElement);