Skip to main content

Built-in Matchers

KTestify ships 12 RecordMatcher<V> implementations, split into raw (String) and Avro (GenericRecord) variants. They are selected automatically by RecordMatcherFactory based on the matchMethod in MatchContext.


Factory resolution table​

matchMethod constantRaw matcherAvro matcher
methodMatchFileFileRecordMatcherAvroFileRecordMatcher
methodMatchKeyValueFileKeyRecordMatcherAvroFileKeyRecordMatcher
methodFieldsToMatchFieldsRecordMatcherAvroFieldsRecordMatcher
methodMatchXMLXmlRecordMatcher❌ ConsumerException
methodMatchXPathXPathRecordMatcher❌ ConsumerException
methodRecordKeyMatchKeyRecordMatcherAvroKeyRecordMatcher
methodMatchAttributesAttributeRecordMatcher<V>❌ ConsumerException
null / blankNoOpRecordMatcher<V>NoOpRecordMatcher<V>
// Usage
RecordMatcher<String> raw = RecordMatcherFactory.forRaw("matchFile");
RecordMatcher<GenericRecord> avro = RecordMatcherFactory.forAvro("matchFile");

Raw matchers (V = String)​

FileRecordMatcher​

Compares record values character-for-character against expected file content after dynamic variable resolution. Supports both single-record and multi-record batch matching (POSITIONAL and LAZY 1-to-1 matching without replacement). Uses StringDiffUtils to produce a coloured ANSI diff on failure.

  • MatchContext fields used: matchFilePaths, matchKeys, keyMatchStrategy, batchMatchStrategy
  • On failure: returns MatchResult.fail(diff, expected, actual)
  • On count mismatch: throws ComparisonException when records.size() != matchFilePaths.size()

FileKeyRecordMatcher​

Asserts both the record key and value. The expected file must contain the key on line 1 and the value from line 2 onwards. Key matching uses the KeyMatchStrategy from MatchContext (defaults to EXACT).

  • MatchContext fields used: matchFilePaths.get(0), keyMatchStrategy

KeyRecordMatcher​

Asserts only the record key, the value is not evaluated. Key matching uses the KeyMatchStrategy from MatchContext (defaults to EXACT).

  • MatchContext fields used: matchKey (falls back to matchFilePaths.get(0) if blank), keyMatchStrategy

FieldsRecordMatcher​

Extracts a character range [from, to) from line line of the record value and compares it against the same range from the expected file. Implemented via FieldMatcherUtils.

  • MatchContext fields used: matchFilePaths.get(0), matchKey (encodes line:from:to)

XmlRecordMatcher​

Parses both the record value and the expected file as XML, optionally removes excluded elements from both, then compares structurally using XMLUtils. Element order does not matter.

  • MatchContext fields used: matchFilePaths.get(0), excludedFields (element name list)
  • Not available for Avro.

XPathRecordMatcher​

Runs one or more XPath expressions against the record value and compares each extracted value against the corresponding line of the expected file.

  • MatchContext fields used: matchFilePaths.get(0), matchKey (comma-separated XPath expressions)
  • Not available for Avro.

NoOpRecordMatcher<V>​

Always returns MatchResult.pass(). Used when matchMethod is null or blank, typically for watcher steps that only care about record presence, not content.


AttributeRecordMatcher<V> (1.1.1)​

Generic, transport agnostic matcher introduced alongside RequestResponseClient<Req, V> for synchronous transports. Asserts one or more entries of ConsumedRecord.getAttributes() against MatchContext.getExpectedAttributes(). Never inspects getValue(), so it works for any V, not only String.

  • MatchContext fields used: expectedAttributes (map of key to expected value)
  • Matching rule: every key in expectedAttributes must be present in the actual record's attributes with an exactly equal String value, only the first record in the list is used
  • On empty expectedAttributes: returns MatchResult.pass() immediately, nothing to assert
  • Typical use: HTTP status code assertions ({"statusCode": "200"}), reusable later by any future transport that populates attributes (gRPC status, MQ reason code, script exit code)
  • Not available for Avro, attributes is populated by synchronous request/response clients, not Avro consumers

Avro matchers (V = GenericRecord)​

All Avro matchers first deserialise the GenericRecord to a JSON Map via AvroUtils.toJsonMap(), then delegate to comparison logic equivalent to their raw counterparts.

AvroFileRecordMatcher​

Avro equivalent of FileRecordMatcher. Converts GenericRecord to a JSON string, excludes fields listed in excludedFields, then compares against the expected file(s). Supports both single-record and multi-record batch matching (POSITIONAL and LAZY 1-to-1 matching without replacement).

  • MatchContext fields used: matchFilePaths, matchKeys, keyMatchStrategy, excludedFields, batchMatchStrategy
  • On count mismatch: throws ComparisonException when records.size() != matchFilePaths.size()

AvroFileKeyRecordMatcher​

Avro equivalent of FileKeyRecordMatcher. Asserts key + Avro-serialised JSON value. Key matching uses the KeyMatchStrategy from MatchContext (defaults to EXACT).


AvroKeyRecordMatcher​

Avro equivalent of KeyRecordMatcher. Key-only assertion; Avro value ignored. Key matching uses the KeyMatchStrategy from MatchContext (defaults to EXACT).


AvroFieldsRecordMatcher​

Avro equivalent of FieldsRecordMatcher. Extracts a character range from the JSON-serialised Avro value.


Key design rules​

  1. excludedFields defaults to Collections.emptyList(), matchers check isEmpty(), never null.
  2. matchFilePaths is always a List<String>, single-record matchers use getFirst(), and batch matchers (FileRecordMatcher, AvroFileRecordMatcher) compare all records against matchFilePaths using batchMatchStrategy (POSITIONAL by default, or LAZY for unordered 1-to-1 matching).
  3. XML/XPath matchers throw ConsumerException when called via RecordMatcherFactory.forAvro().
  4. NoOpRecordMatcher is the default when no match method is configured.
  5. expectedAttributes defaults to Collections.emptyMap(), AttributeRecordMatcher checks isEmpty(), never null, same convention as excludedFields.
  6. keyMatchStrategy defaults to KeyMatchStrategy.EXACT, key matchers (KeyRecordMatcher, FileKeyRecordMatcher, AvroKeyRecordMatcher, AvroFileKeyRecordMatcher) and the fetch-time key filter (KafkaRecordFetcher.passesKeyFilter()) both delegate to KeyMatchStrategy.matches(expected, actual). Available strategies: EXACT, CONTAINS, STARTS_WITH, ENDS_WITH, REGEX.
  7. batchMatchStrategy defaults to BatchMatchStrategy.POSITIONAL. Available strategies: POSITIONAL and LAZY.