# Avro Assertions

> Assert Avro-serialised Kafka records against JSON files or specific field values.

Source: https://docs.ktestify.xyz/docs/write-tests/assertions/avro-matchers

Avro matchers deserialise `GenericRecord` values (via Schema Registry) and compare them as JSON or by individual fields.

---

## File match: `Then expected record from file based on schema`

Fetches an Avro record, converts it to JSON, and compares it against an expected JSON file. Excludes specified top-level keys from comparison.

```gherkin
Then expected record from file based on schema
  | topicAlias | file           | excludedKeys      | consumerReadTimeout |
  | orders-out | expected.json  | createdAt,eventId | 30                  |
```

| Column | Type | Required | Description |
|---|---|---|---|
| `topicAlias` | `string` | ✅ | Alias of a declared output topic |
| `file` | `string` | ✅ | Expected JSON file path, relative to assets directory |
| `excludedKeys` | `string` | ❌ | Comma-separated list of Avro field names to ignore during comparison |
| `expectedRecordKey` | `string` | ❌ | Filter: only accept records with this exact key |
| `consumerReadTimeout` | `integer` | ❌ | Max seconds to wait for a record |
| `consumerDeltaTime` | `integer` | ❌ | How far back (seconds) to seek |

---

## Key + file match: `Then expected record with key and value from file based on schema`

Asserts both the record **key** and **value** (as Avro → JSON) against a file.

```gherkin
Then expected record with key and value from file based on schema
  | topicAlias | file          | excludedKeys |
  | orders-out | expected.json | timestamp    |
```

---

## Field value match: `Then expected record based on schema should have fields matching from given value`

Asserts one or more specific Avro field values without a file.

### Single field

Use the `key` / `value` columns to assert a single field:

```gherkin
Then expected record based on schema should have fields matching from given value
  | topicAlias | key       | value     |
  | orders-out | status    | PROCESSED |
```

### Multiple fields

Use the `keys` / `values` columns to assert multiple fields in a single step. Separate field names and expected values
with semicolons (`;`). Every pair must match for the assertion to pass.

```gherkin
Then expected record based on schema should have fields matching from given value
  | topicAlias | keys          | values      |
  | orders-out | status;amount | PENDING;99 |
```

The above validates that `status == PENDING` **and** `amount == 99`.

| Column | Type | Required | Description |
|---|---|---|---|
| `topicAlias` | `string` | ✅ | Alias of a declared output topic |
| `key` | `string` | ❌* | Avro field name (single-field mode) |
| `value` | `string` | ❌* | Expected field value (single-field mode) |
| `keys` | `string` | ❌* | Semicolon-separated Avro field names (multi-field mode) |
| `values` | `string` | ❌* | Semicolon-separated expected values (multi-field mode) |
| `consumerReadTimeout` | `integer` | ❌ | Max seconds to wait for a record |
| `consumerDeltaTime` | `integer` | ❌ | How far back (seconds) to seek |

\* Either `key` + `value` (single field) **or** `keys` + `values` (multiple fields) must be provided. The two modes
are mutually exclusive.

---

## Key match: `Then expected Avro record should match key`

Asserts only the **record key**; the Avro value is ignored.

```gherkin
Then expected record based on schema should match key
  | topicAlias | expectedRecordKey |
  | orders-out | ord-001           |
```

---

## Positional fields: `Then expected record based on schema should have fields matching from file`

Assert a specific character range of the JSON-serialised Avro value.

```gherkin
Then expected record based on schema should have fields matching from file
  | topicAlias | file         | line | from | to |
  | orders-out | expected.txt | 1    | 0    | 10 |
```

---

## Multiple rows, same topic

Single-record Avro assertion steps (file match, field value match, key-only, positional fields) support multiple rows validated sequentially, in order, as long as every row targets the **same physical topic**.

All rows share one pinned `referenceTimestamp` so their delta-time seek windows don't drift. Mixing topics throws `TopicMismatchException` before any consumer call is made. See [Multi-row DataTables →](../advanced/multi-row-datatables) for the full rules.

---

## See also

- [Batch Avro assertions →](batch-assertions)
- [Schemas background step →](../background/schemas)
- [Configuration →](../../getting-started/configuration)
- [Multi-row DataTables →](../advanced/multi-row-datatables)
