Skip to content
Stefan Bodewig edited this page Apr 21, 2018 · 8 revisions

Hamcrest CompareMatcher and NUnit CompareConstraint

XMLUnit for Java provides a Hamcrest matcher named CompareMatcher and XMLUnit.NET has an NUnit Constraint1 named CompareConstraint that can be used to compare two XML sources with each other.

Basic Example

This example will throw an AssertionError: "Expected attribute value 'abc' but was 'xyz'".

final String control = "<a><b attr=\"abc\"></b></a>";
final String test = "<a><b attr=\"xyz\"></b></a>";

assertThat(test, CompareMatcher.isIdenticalTo(control));

The corresponding NUnit test code is

string control = "<a><b attr=\"abc\"></b></a>";
string test = "<a><b attr=\"xyz\"></b></a>";

Assert.That(test, CompareConstraint.IsIdenticalTo(control));

Test-Objects and Control-Objects

You can compare any kind of Objects with each other which can be used as a XML sources.

See: Providing Input To XMLUnit - Input.from(Object)

similar vs identical

The Difference between identical and similar is decided by the default DifferenceEvaluator unless you override it.

fluent API

The matcher and constraint can be configured via a fluent API:

CompareMatcher.isSimilarTo(control)
    .ignoreComments() // [1]
    .ignoreWhitespace() // [2]
    .normalizeWhitespace() // [3]
    .throwComparisonFailure() // [4]
    .withComparisonFormatter(comparisonFormatter) // [5]
    .withComparisonListeners(comparisonListeners) // [6]
    .withDifferenceEvaluator(differenceEvaluator) // [7]
    .withDifferenceListeners(comparisonListeners) // [8]
    .withNodeMatcher(nodeMatcher) // [9]
    .withAttributeFilter(attributeFilter) // [10]
    .withNodeFilter(nodeFilter) // [11]
    .withDocumentBuilderFactory(dbf) // [12]
    .ignoreElementContentWhitespace(); // [13]

and

CompareConstraint.IsSimilarTo(control)
    .IgnoreComments() // [1]
    .IgnoreWhitespace() // [2]
    .NormalizeWhitespace() // [3]
    .WithComparisonFormatter(comparisonFormatter) // [5]
    .WithComparisonListeners(comparisonListeners) // [6]
    .WithDifferenceEvaluator(differenceEvaluator) // [7]
    .WithDifferenceListeners(comparisonListeners) // [8]
    .WithNodeMatcher(nodeMatcher) // [9]
    .WithAttributeFilter(attributeFilter) // [10]
    .WithNodeFilter(nodeFilter) // [11]
    .IgnoreElementContentWhitespace(); // [13]
  1. ignoreComments():
    will stripping all comments from the test- and control-XML before comparing.
  2. ignoreWhitespace():
    will removing all empty text nodes and trimming the non-empty ones from the test- and control-XML before comparing. If all you need is to remove text nodes solely consisting of whitespace, then you want to use ignoreElementContentWhitespace.
  3. normalizeWhitespace():
    will removing all empty text nodes and normalizing the non-empty ones from the test- and control-XML before comparing. With "normalized" in this context means all whitespace characters are replaced by space characters and consecutive whitespace characters are collapsed.
  4. throwComparisonFailure():
    This will throw a org.junit.ComparisonFailure in case of differences. Eclipse, IntelliJ and NetBeans can than show you a nice Diff-View of the differences.
    See throwComparisonFailure. This is only available for XMLUnit for Java's CompareMatcher
  5. withComparisonFormatter():
    Use a custom Formatter for the Error Messages.
    See ComparisonFormatter.
  6. withComparisonListeners():
    Registers a listener that is notified of each comparison.
    See ComparisonListener.
  7. withDifferenceEvaluator():
    Provide your own custom DifferenceEvaluator implementation.
    See DifferenceEvaluator.
  8. withDifferenceListeners():
    Registers a listener that is notified of each comparison with outcome other than ComparisonResult.EQUAL.
    See ComparisonListener.
  9. withNodeMatcher():
    Sets the strategy for selecting nodes to compare.
    See NodeMatcher.
  10. withAttributeFilter(): Optional strategy that allows certain attributes to be ignore completely. See AttributeFilter.
  11. withNodeFilter(): Optional strategy that allows certain nodes to be ignore completely. See NodeFilter.
  12. withDocumentBuilderFactory(): Use the given DocumentBuilderFactory when creating a document from the test or control source. Only available in XMLUnit for Java - since XMLUnit 2.2.0.
  13. ignoreElementContentWhitespace(): will removing all text nodes solely consisting of whitespace (AKA as element content whitespace) - since XMLUnit 2.6.0.

throwComparisonFailure()

Instead of Matcher returning false a org.junit.ComparisonFailure will be thrown.

The advantage over the standard Matcher behavior is, that a ComparisonFailure can provide the effected Control-Node and Test-Node in separate Properties. Eclipse, NetBeans and IntelliJ can provide a nice DIFF-View for the two values. ComparisonFailure is also used in org.junit.Assert.assertEquals(Object, Object) if both values are Strings:

ElementSelector migration

The only disadvantage is, that you can't combine the CompareMatcher with other Matchers (like org.hamcrest.CoreMatchers.not(Object)) anymore. The following code will NOT WORK properly: assertThat(test, not(isSimilarTo(control).throwComparisonFailure()))

1: Actually there are two of them, one for NUnit 2.x and one for NUnit 3.x.