) actual;
Comparator super ELEMENT> comparator = sortedSet.comparator();
if (comparator != null) usingElementComparator(sortedSet.comparator());
}
}
+ /**
+ * Configures the {@link AssertFactory} used to create assertions whenever a navigation method is invoked.
+ *
+ * For example, given an {@code Iterable}, {@link Assertions#assertThat(String)} can be configured
+ * as the {@code AssertFactory} to be used for navigation methods like
+ * {@link #first()}, {@link #last()}, {@link #element(int)}, and {@link #singleElement()}:
+ *
+ * Iterable<String> people = List.of("Luke", "Leia");
+ *
+ * assertThat(people).withElementAssert(Assertions::assertThat)
+ * .first()
+ * .startsWith("Lu");
+ *
+ * This is also helpful for custom assertions, where users of such assertions can already benefit from
+ * type-specific assertions when invoking a navigation method, without additional effort. For example,
+ * given a {@code Iterable} and a {@code PersonAssert} custom assertion, you can write:
+ *
+ * Iterable<Person> people = getPeople();
+ *
+ * assertThat(people).withElementAssert(PersonAssert::new)
+ * .first()
+ * .hasName("Luke")
+ * .hasLightSaber();
+ *
+ *
+ * @param the type of the assertion to be created when a navigation method is invoked
+ * @param assertFactory the factory responsible for creating an {@link ASSERT} instance from an {@link ELEMENT};
+ * must not be {@code null}.
+ * @return an {@link AbstractIterableAssert} whose element assertions are created using the given {@code assertFactory};
+ * the returned instance allows fluent type-specific assertions when navigating to a specific element.
+ * @since 3.28.0
+ */
+ public > AbstractIterableAssert, ACTUAL, ELEMENT, ASSERT> withElementAssert(AssertFactory assertFactory) {
+ return new FactoryBasedAssert<>(actual, assertFactory);
+ }
+
/**
* {@inheritDoc}
*/
@@ -2256,7 +2293,7 @@ public RecursiveComparisonAssert> usingRecursiveComparison(RecursiveComparison
*
* The recursive algorithm employs cycle detection, so object graphs with cyclic references can safely be asserted over without causing looping.
*
- * This method enables recursive asserting using default configuration, which means all fields of all objects have the
+ *
This method enables recursive asserting using default configuration, which means all fields of all objects have the
* {@link java.util.function.Predicate} applied to them (including primitive fields), no fields are excluded, but:
*
* - The recursion does not enter into Java Class Library types (java.*, javax.*)
@@ -2848,7 +2885,7 @@ public SELF filteredOnAssertions(Consumer super ELEMENT> elementAssertions) {
* Filters the iterable under test keeping only elements matching the given assertions specified with a {@link ThrowingConsumer}.
*
* This is the same assertion as {@link #filteredOnAssertions(Consumer)} but the given consumer can throw checked exceptions.
- * More precisely, {@link RuntimeException} and {@link AssertionError} are rethrown as they are and {@link Throwable} wrapped in a {@link RuntimeException}.
+ * More precisely, {@link RuntimeException} and {@link AssertionError} are rethrown as they are and {@link Throwable} wrapped in a {@link RuntimeException}.
*
* Example: check young hobbits whose age < 34:
*
@@ -3053,8 +3090,8 @@ public ELEMENT_ASSERT element(int index) {
}
/**
- * Allow to perform assertions on the elements corresponding to the given indices
- * (the iterable {@link Iterable} under test is changed to an iterable with the selected elements).
+ * Allow to perform assertions on the elements corresponding to the given indices
+ * (the iterable {@link Iterable} under test is changed to an iterable with the selected elements).
*
* Example:
*
Iterable<TolkienCharacter> hobbits = newArrayList(frodo, sam, pippin);
@@ -3204,7 +3241,7 @@ public ELEMENT_ASSERT singleElement() {
}
/**
- * Verifies that the {@link Iterable} under test contains a single element and allows to perform assertions on that element,
+ * Verifies that the {@link Iterable} under test contains a single element and allows to perform assertions on that element,
* the assertions are strongly typed according to the given {@link AssertFactory} parameter.
*
* This is a shorthand for hasSize(1).first(assertFactory).
@@ -3797,4 +3834,38 @@ private SELF internalFilteredOn(Predicate super ELEMENT> predicate) {
List extends ELEMENT> filteredIterable = stream(actual.spliterator(), false).filter(predicate).collect(toList());
return newAbstractIterableAssert(filteredIterable).withAssertionState(myself);
}
+
+ /**
+ * This class exists to maintain binary compatibility in version 3 and will be merged into {@link IterableAssert}
+ * in version 4.
+ */
+ // @format:off
+ private static class FactoryBasedAssert,
+ ACTUAL extends Iterable extends ELEMENT>,
+ ELEMENT,
+ ELEMENT_ASSERT extends AbstractAssert extends ELEMENT_ASSERT, ELEMENT>>
+ extends AbstractIterableAssert {
+ // @format:on
+
+ private final AssertFactory assertFactory;
+
+ private FactoryBasedAssert(ACTUAL actual, AssertFactory assertFactory) {
+ super(actual, FactoryBasedAssert.class);
+ this.assertFactory = assertFactory;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ protected ELEMENT_ASSERT toAssert(ELEMENT value, String description) {
+ return assertFactory.createAssert(value).as(description);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ protected SELF newAbstractIterableAssert(Iterable extends ELEMENT> iterable) {
+ return (SELF) new FactoryBasedAssert<>(iterable, assertFactory);
+ }
+
+ }
+
}
diff --git a/assertj-core/src/main/java/org/assertj/core/api/AbstractIterableSizeAssert.java b/assertj-core/src/main/java/org/assertj/core/api/AbstractIterableSizeAssert.java
index c1bcf963e1..d734d67aa8 100644
--- a/assertj-core/src/main/java/org/assertj/core/api/AbstractIterableSizeAssert.java
+++ b/assertj-core/src/main/java/org/assertj/core/api/AbstractIterableSizeAssert.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2025 the original author or authors.
+ * Copyright 2012-2026 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,7 +19,7 @@
public abstract class AbstractIterableSizeAssert,
ACTUAL extends Iterable extends ELEMENT>,
ELEMENT,
- ELEMENT_ASSERT extends AbstractAssert>
+ ELEMENT_ASSERT extends AbstractAssert extends ELEMENT_ASSERT, ELEMENT>>
extends AbstractIntegerAssert> {
//@format:on
diff --git a/assertj-core/src/main/java/org/assertj/core/api/AbstractIteratorAssert.java b/assertj-core/src/main/java/org/assertj/core/api/AbstractIteratorAssert.java
index 805811779b..7547b7ed59 100644
--- a/assertj-core/src/main/java/org/assertj/core/api/AbstractIteratorAssert.java
+++ b/assertj-core/src/main/java/org/assertj/core/api/AbstractIteratorAssert.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2025 the original author or authors.
+ * Copyright 2012-2026 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/assertj-core/src/main/java/org/assertj/core/api/AbstractListAssert.java b/assertj-core/src/main/java/org/assertj/core/api/AbstractListAssert.java
index 96905c4e73..abcfe0fa39 100644
--- a/assertj-core/src/main/java/org/assertj/core/api/AbstractListAssert.java
+++ b/assertj-core/src/main/java/org/assertj/core/api/AbstractListAssert.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2025 the original author or authors.
+ * Copyright 2012-2026 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -45,7 +45,7 @@
public abstract class AbstractListAssert,
ACTUAL extends List extends ELEMENT>,
ELEMENT,
- ELEMENT_ASSERT extends AbstractAssert>
+ ELEMENT_ASSERT extends AbstractAssert extends ELEMENT_ASSERT, ELEMENT>>
extends AbstractCollectionAssert
implements IndexedObjectEnumerableAssert {
// @format:on
@@ -57,6 +57,21 @@ protected AbstractListAssert(ACTUAL actual, Class> selfType) {
super(actual, selfType);
}
+ /**
+ * {@inheritDoc}
+ *
+ * @param the type of the assertion to be created when a navigation method is invoked
+ * @param assertFactory the factory responsible for creating an {@link ASSERT} instance from an {@link ELEMENT};
+ * must not be {@code null}.
+ * @return an {@link AbstractListAssert} whose element assertions are created using the given {@code assertFactory};
+ * the returned instance allows fluent type-specific assertions when navigating to a specific element.
+ * @since 3.28.0
+ */
+ @Override
+ public > AbstractListAssert, ACTUAL, ELEMENT, ASSERT> withElementAssert(AssertFactory assertFactory) {
+ return new FactoryBasedAssert<>(actual, assertFactory);
+ }
+
/** {@inheritDoc} */
@Override
public SELF contains(ELEMENT value, Index index) {
@@ -399,4 +414,37 @@ public SELF withThreadDumpOnError() {
return super.withThreadDumpOnError();
}
+ /**
+ * This class exists to maintain binary compatibility in version 3 and will be merged into {@link ListAssert}
+ * in version 4.
+ */
+ // @format:off
+ private static class FactoryBasedAssert,
+ ACTUAL extends List extends ELEMENT>,
+ ELEMENT,
+ ELEMENT_ASSERT extends AbstractAssert extends ELEMENT_ASSERT, ELEMENT>>
+ extends AbstractListAssert {
+ // @format:on
+
+ private final AssertFactory assertFactory;
+
+ private FactoryBasedAssert(ACTUAL actual, AssertFactory assertFactory) {
+ super(actual, FactoryBasedAssert.class);
+ this.assertFactory = assertFactory;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ protected ELEMENT_ASSERT toAssert(ELEMENT value, String description) {
+ return assertFactory.createAssert(value).as(description);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ protected SELF newAbstractIterableAssert(Iterable extends ELEMENT> iterable) {
+ return (SELF) new FactoryBasedAssert<>((List extends ELEMENT>) iterable, assertFactory);
+ }
+
+ }
+
}
diff --git a/assertj-core/src/main/java/org/assertj/core/api/AbstractLocalDateAssert.java b/assertj-core/src/main/java/org/assertj/core/api/AbstractLocalDateAssert.java
index cc7e2a00a0..fe5d3e8213 100644
--- a/assertj-core/src/main/java/org/assertj/core/api/AbstractLocalDateAssert.java
+++ b/assertj-core/src/main/java/org/assertj/core/api/AbstractLocalDateAssert.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2025 the original author or authors.
+ * Copyright 2012-2026 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/assertj-core/src/main/java/org/assertj/core/api/AbstractLocalDateTimeAssert.java b/assertj-core/src/main/java/org/assertj/core/api/AbstractLocalDateTimeAssert.java
index 86e5180abc..3d803505fc 100644
--- a/assertj-core/src/main/java/org/assertj/core/api/AbstractLocalDateTimeAssert.java
+++ b/assertj-core/src/main/java/org/assertj/core/api/AbstractLocalDateTimeAssert.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2025 the original author or authors.
+ * Copyright 2012-2026 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/assertj-core/src/main/java/org/assertj/core/api/AbstractLocalTimeAssert.java b/assertj-core/src/main/java/org/assertj/core/api/AbstractLocalTimeAssert.java
index 5ea30e62c2..0d92e7960b 100644
--- a/assertj-core/src/main/java/org/assertj/core/api/AbstractLocalTimeAssert.java
+++ b/assertj-core/src/main/java/org/assertj/core/api/AbstractLocalTimeAssert.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2025 the original author or authors.
+ * Copyright 2012-2026 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/assertj-core/src/main/java/org/assertj/core/api/AbstractLongAdderAssert.java b/assertj-core/src/main/java/org/assertj/core/api/AbstractLongAdderAssert.java
index 74d75b0b8e..fa026ad1f1 100644
--- a/assertj-core/src/main/java/org/assertj/core/api/AbstractLongAdderAssert.java
+++ b/assertj-core/src/main/java/org/assertj/core/api/AbstractLongAdderAssert.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2025 the original author or authors.
+ * Copyright 2012-2026 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/assertj-core/src/main/java/org/assertj/core/api/AbstractLongArrayAssert.java b/assertj-core/src/main/java/org/assertj/core/api/AbstractLongArrayAssert.java
index 3156603801..cd5f99aab1 100644
--- a/assertj-core/src/main/java/org/assertj/core/api/AbstractLongArrayAssert.java
+++ b/assertj-core/src/main/java/org/assertj/core/api/AbstractLongArrayAssert.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2025 the original author or authors.
+ * Copyright 2012-2026 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/assertj-core/src/main/java/org/assertj/core/api/AbstractLongAssert.java b/assertj-core/src/main/java/org/assertj/core/api/AbstractLongAssert.java
index 002980d8c4..2bfab86d3d 100644
--- a/assertj-core/src/main/java/org/assertj/core/api/AbstractLongAssert.java
+++ b/assertj-core/src/main/java/org/assertj/core/api/AbstractLongAssert.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2025 the original author or authors.
+ * Copyright 2012-2026 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/assertj-core/src/main/java/org/assertj/core/api/AbstractMapAssert.java b/assertj-core/src/main/java/org/assertj/core/api/AbstractMapAssert.java
index 3e701f944b..943bb19995 100644
--- a/assertj-core/src/main/java/org/assertj/core/api/AbstractMapAssert.java
+++ b/assertj-core/src/main/java/org/assertj/core/api/AbstractMapAssert.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2025 the original author or authors.
+ * Copyright 2012-2026 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -2159,6 +2159,29 @@ private static List