assertj: AssertJ 3.27.7 lab (soft assertions, recursive comparison, custom and generated assertions)

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01CifR2BE7PBvRy5hT8TS9oz
This commit is contained in:
2026-10-26 01:57:10 +00:00
co-authored by Claude Sonnet 5.5
parent 08e063d22e
commit 9d89323864
50 changed files with 1427 additions and 0 deletions
@@ -0,0 +1,12 @@
startsWith failure:
Expecting actual:
"Hello, AssertJ"
to start with:
"Goodbye"
isEqualTo failure:
expected: 43
but was: 42
as(...) failure:
[answer to everything]
expected: 43
but was: 42
@@ -0,0 +1,2 @@
assertThat(1); -> threw: nothing
assertThat("any value"); -> threw: nothing
@@ -0,0 +1,7 @@
BigDecimal 2.00 isEqualTo 2.0:
expected: 2.0
but was: 2.00
double 0.1+0.2 isEqualTo 0.3:
expected: 0.3
but was: 0.30000000000000004
0.1 + 0.2 = 0.30000000000000004
+4
View File
@@ -0,0 +1,4 @@
Optional.empty() isPresent:
Expecting Optional to contain a value but it was empty.
null String startsWith:
Expecting actual not to be null
+17
View File
@@ -0,0 +1,17 @@
containsExactly, wrong order:
Expecting actual:
["BOOK-1", "PEN-7", "BAG-3"]
to contain exactly (and in same order):
["PEN-7", "BOOK-1", "BAG-3"]
but there were differences at these indexes:
- element at index 0: expected "PEN-7" but was "BOOK-1"
- element at index 1: expected "BOOK-1" but was "PEN-7"
containsExactlyInAnyOrder, one missing and one unexpected:
Expecting actual:
["BOOK-1", "PEN-7", "BAG-3"]
to contain exactly in any order:
["BOOK-1", "PEN-7", "HAT-9"]
elements not found:
["HAT-9"]
and elements not expected:
["BAG-3"]
@@ -0,0 +1,9 @@
extracting(sku, quantity) with one wrong quantity:
Expecting actual:
[("BOOK-1", 2), ("PEN-7", 10), ("BAG-3", 1)]
to contain exactly (and in same order):
[("BOOK-1", 2), ("PEN-7", 11), ("BAG-3", 1)]
but some elements were not found:
[("PEN-7", 11)]
and others were not expected:
[("PEN-7", 10)]
+13
View File
@@ -0,0 +1,13 @@
allSatisfy, one element violates the rule: (stack frames omitted)
Expecting all elements of:
[OrderLine[sku=BOOK-1, quantity=2, unitPrice=12.50],
OrderLine[sku=PEN-7, quantity=10, unitPrice=1.20],
OrderLine[sku=BAG-3, quantity=1, unitPrice=40.00]]
to satisfy given requirements, but these elements did not:
OrderLine[sku=PEN-7, quantity=10, unitPrice=1.20]
error: java.lang.AssertionError: [quantity of PEN-7]
Expecting actual:
10
to be less than:
5
+7
View File
@@ -0,0 +1,7 @@
containsEntry with wrong value:
Expecting map:
{"BOOK-1"=4, "PEN-7"=0}
to contain entries:
["PEN-7"=5]
but the following map entries had different values:
["PEN-7"=0 (expected: 5)]
+18
View File
@@ -0,0 +1,18 @@
expected exception, nothing thrown: (stack frames omitted)
Expecting code to raise a throwable.
wrong message: (stack frames omitted)
Expecting message to be:
"payment failed"
but was:
"payment failed for order o-45"
Throwable that failed the check:
lab.assertj.custom.CheckoutException: payment failed for order o-45
Caused by: java.lang.IllegalStateException: gateway unavailable
Caused by: java.io.IOException: connection reset by gateway
wrong type: (stack frames omitted)
Expecting actual throwable to be an instance of:
java.lang.IllegalStateException
but was:
lab.assertj.custom.CheckoutException: payment failed for order o-45
@@ -0,0 +1,3 @@
three wrong expectations, hard assertions:
expected: "o-1"
but was: "o-9"
@@ -0,0 +1,15 @@
exception type: org.assertj.core.error.AssertJMultipleFailuresError
message:
Multiple Failures (3 failures)
-- failure 1 --
expected: "o-1"
but was: "o-9"
at SoftAssertionsTest.lambda$assertSoftlyReportsAll$1(SoftAssertionsTest.java:48)
-- failure 2 --
expected: PAID
but was: NEW
at SoftAssertionsTest.lambda$assertSoftlyReportsAll$1(SoftAssertionsTest.java:49)
-- failure 3 --
expected: 75
but was: 99.00
at SoftAssertionsTest.lambda$assertSoftlyReportsAll$1(SoftAssertionsTest.java:50)
+2
View File
@@ -0,0 +1,2 @@
errors collected but not thrown: 2
assertAll() throws: org.assertj.core.error.AssertJMultipleFailuresError
+1
View File
@@ -0,0 +1 @@
thrown: java.lang.NullPointerException
@@ -0,0 +1,3 @@
two Customers with identical fields, isEqualTo:
expected: "Customer{id=7, name=Asha Patil, [email protected], address=Address[street=12 MG Road, city=Pune, postcode=411001], tags=[vip, newsletter], creditLimit=5000.00} (Customer@73c3cd09)"
but was: "Customer{id=7, name=Asha Patil, [email protected], address=Address[street=12 MG Road, city=Pune, postcode=411001], tags=[vip, newsletter], creditLimit=5000.00} (Customer@74f827ad)"
@@ -0,0 +1,20 @@
DTO vs entity with withStrictTypeChecking():
Expecting actual:
CustomerDto[id=7, name=Asha Patil, [email protected], address=Address[street=12 MG Road, city=Pune, postcode=411001], tags=[vip, newsletter], createdAt=2026-10-01T10:00:00Z, creditLimit=5000.00]
to be equal to:
Customer{id=7, name=Asha Patil, [email protected], address=Address[street=12 MG Road, city=Pune, postcode=411001], tags=[vip, newsletter], creditLimit=5000.00}
when recursively comparing field by field, but found the following difference:
Top level actual and expected objects differ:
- actual value : CustomerDto[id=7, name=Asha Patil, [email protected], address=Address[street=12 MG Road, city=Pune, postcode=411001], tags=[vip, newsletter], createdAt=2026-10-01T10:00:00Z, creditLimit=5000.00]
- expected value: Customer{id=7, name=Asha Patil, [email protected], address=Address[street=12 MG Road, city=Pune, postcode=411001], tags=[vip, newsletter], creditLimit=5000.00}
actual and expected are considered different since the comparison enforces strict type check and expected type lab.assertj.domain.Customer is not a subtype of actual type lab.assertj.domain.CustomerDto
The recursive comparison was performed with this configuration:
- no equals methods were used in the comparison EXCEPT for java JDK types since introspecting JDK types is forbidden in java 17+ (use withEqualsForType to register a specific way to compare a JDK type if you need it)
- these types were compared with the following comparators:
- java.lang.Double -> DoubleComparator[precision=1.0E-15]
- java.lang.Float -> FloatComparator[precision=1.0E-6]
- java.nio.file.Path -> lexicographic comparator (Path natural order)
- actual and expected objects and their fields were considered different when of incompatible types (i.e. expected type does not extend actual's type) even if all their fields match, for example a Person instance will never match a PersonDto (call strictTypeChecking(false) to change that behavior).
- the introspection strategy used was: DefaultRecursiveComparisonIntrospectionStrategy
@@ -0,0 +1,35 @@
recursive comparison, four fields differ:
Expecting actual:
Customer{id=7, name=Asha Patil, [email protected], address=Address[street=12 MG Road, city=Mumbai, postcode=411001], tags=[vip], creditLimit=5000.0}
to be equal to:
Customer{id=7, name=Asha Patil, [email protected], address=Address[street=12 MG Road, city=Pune, postcode=411001], tags=[vip, newsletter], creditLimit=5000.00}
when recursively comparing field by field, but found the following 4 differences:
field/property 'address.city' differ:
- actual value : "Mumbai"
- expected value: "Pune"
Compared objects have java types and were thus compared with equals method
field/property 'creditLimit' differ:
- actual value : 5000.0
- expected value: 5000.00
Compared objects have java types and were thus compared with equals method
field/property 'email' differ:
- actual value : "[email protected]"
- expected value: "[email protected]"
Compared objects have java types and were thus compared with equals method
field/property 'tags' differ:
- actual value : ["vip"]
- expected value: ["vip", "newsletter"]
actual and expected values are collections of different size, actual size=1 when expected size=2
The recursive comparison was performed with this configuration:
- no equals methods were used in the comparison EXCEPT for java JDK types since introspecting JDK types is forbidden in java 17+ (use withEqualsForType to register a specific way to compare a JDK type if you need it)
- these types were compared with the following comparators:
- java.lang.Double -> DoubleComparator[precision=1.0E-15]
- java.lang.Float -> FloatComparator[precision=1.0E-6]
- java.nio.file.Path -> lexicographic comparator (Path natural order)
- actual and expected objects and their fields were compared field by field recursively even if they were not of the same type, this allows for example to compare a Person to a PersonDto (call strictTypeChecking(true) to change that behavior).
- the introspection strategy used was: DefaultRecursiveComparisonIntrospectionStrategy
+89
View File
@@ -0,0 +1,89 @@
no knobs:
Expecting actual:
Customer{id=99, name=Asha Patil, [email protected], address=Address[street=12 MG Road, city=Pune, postcode=411001], tags=[newsletter, vip], creditLimit=5000.0}
to be equal to:
Customer{id=7, name=Asha Patil, [email protected], address=Address[street=12 MG Road, city=Pune, postcode=411001], tags=[vip, newsletter], creditLimit=5000.00}
when recursively comparing field by field, but found the following 5 differences:
field/property 'createdAt' differ:
- actual value : 2026-10-26T01:00:00Z
- expected value: 2026-10-01T10:00:00Z
Compared objects have java types and were thus compared with equals method
field/property 'creditLimit' differ:
- actual value : 5000.0
- expected value: 5000.00
Compared objects have java types and were thus compared with equals method
field/property 'id' differ:
- actual value : 99L
- expected value: 7L
Compared objects have java types and were thus compared with equals method
field/property 'tags[0]' differ:
- actual value : "newsletter"
- expected value: "vip"
Compared objects have java types and were thus compared with equals method
field/property 'tags[1]' differ:
- actual value : "vip"
- expected value: "newsletter"
Compared objects have java types and were thus compared with equals method
The recursive comparison was performed with this configuration:
- no equals methods were used in the comparison EXCEPT for java JDK types since introspecting JDK types is forbidden in java 17+ (use withEqualsForType to register a specific way to compare a JDK type if you need it)
- these types were compared with the following comparators:
- java.lang.Double -> DoubleComparator[precision=1.0E-15]
- java.lang.Float -> FloatComparator[precision=1.0E-6]
- java.nio.file.Path -> lexicographic comparator (Path natural order)
- actual and expected objects and their fields were compared field by field recursively even if they were not of the same type, this allows for example to compare a Person to a PersonDto (call strictTypeChecking(true) to change that behavior).
- the introspection strategy used was: DefaultRecursiveComparisonIntrospectionStrategy
everything but ignoringCollectionOrder():
Expecting actual:
Customer{id=99, name=Asha Patil, [email protected], address=Address[street=12 MG Road, city=Pune, postcode=411001], tags=[newsletter, vip], creditLimit=5000.0}
to be equal to:
Customer{id=7, name=Asha Patil, [email protected], address=Address[street=12 MG Road, city=Pune, postcode=411001], tags=[vip, newsletter], creditLimit=5000.00}
when recursively comparing field by field, but found the following 2 differences:
field/property 'tags[0]' differ:
- actual value : "newsletter"
- expected value: "vip"
Compared objects have java types and were thus compared with equals method
field/property 'tags[1]' differ:
- actual value : "vip"
- expected value: "newsletter"
Compared objects have java types and were thus compared with equals method
The recursive comparison was performed with this configuration:
- the following fields were ignored in the comparison: id, createdAt
- no equals methods were used in the comparison EXCEPT for java JDK types since introspecting JDK types is forbidden in java 17+ (use withEqualsForType to register a specific way to compare a JDK type if you need it)
- these types were compared with the following comparators:
- java.lang.Double -> DoubleComparator[precision=1.0E-15]
- java.lang.Float -> FloatComparator[precision=1.0E-6]
- java.math.BigDecimal -> BigDecimal compared with compareTo (scale ignored)
- java.nio.file.Path -> lexicographic comparator (Path natural order)
- actual and expected objects and their fields were compared field by field recursively even if they were not of the same type, this allows for example to compare a Person to a PersonDto (call strictTypeChecking(true) to change that behavior).
- the introspection strategy used was: DefaultRecursiveComparisonIntrospectionStrategy
everything but the BigDecimal comparator:
Expecting actual:
Customer{id=99, name=Asha Patil, [email protected], address=Address[street=12 MG Road, city=Pune, postcode=411001], tags=[newsletter, vip], creditLimit=5000.0}
to be equal to:
Customer{id=7, name=Asha Patil, [email protected], address=Address[street=12 MG Road, city=Pune, postcode=411001], tags=[vip, newsletter], creditLimit=5000.00}
when recursively comparing field by field, but found the following difference:
field/property 'creditLimit' differ:
- actual value : 5000.0
- expected value: 5000.00
Compared objects have java types and were thus compared with equals method
The recursive comparison was performed with this configuration:
- the following fields were ignored in the comparison: id, createdAt
- no equals methods were used in the comparison EXCEPT for java JDK types since introspecting JDK types is forbidden in java 17+ (use withEqualsForType to register a specific way to compare a JDK type if you need it)
- collection order was ignored in all fields in the comparison
- these types were compared with the following comparators:
- java.lang.Double -> DoubleComparator[precision=1.0E-15]
- java.lang.Float -> FloatComparator[precision=1.0E-6]
- java.nio.file.Path -> lexicographic comparator (Path natural order)
- actual and expected objects and their fields were compared field by field recursively even if they were not of the same type, this allows for example to compare a Person to a PersonDto (call strictTypeChecking(true) to change that behavior).
- the introspection strategy used was: DefaultRecursiveComparisonIntrospectionStrategy
@@ -0,0 +1,10 @@
hasNumber, wrong:
Expected invoice number to be <INV-2026-002> but was <INV-2026-001>
isArithmeticallyConsistent, wrong:
Expected gross <118.00> (net 100.00 + tax 18.00) but declared gross was <120>
as("billing currency").isIn("USD"):
[billing currency]
expected: "USD"
but was: "INR"
null actual:
Expecting actual not to be null
+8
View File
@@ -0,0 +1,8 @@
allOf(upperCase, shortWord) on "Abcdef":
Expecting actual:
"Abcdef"
to be:
[✗] all of:[
[✗] upper case,
[✗] at most 4 characters
]
@@ -0,0 +1,18 @@
hasStatus(SHIPPED):
Expecting status of:
<Order{id=o-1, status=PAID, total=75.00}>
to be:
<SHIPPED>
but was:
<PAID>
isNotPaid():
Expecting that actual Order is not paid but is.
hasTotal(new BigDecimal("75")) against 75.00:
Expecting total of:
<Order{id=o-1, status=PAID, total=75.00}>
to be:
<75>
but was:
<75.00>
null actual:
Expecting actual not to be null
@@ -0,0 +1,10 @@
generated SoftAssertions, one failing hasStatus:
Multiple Failures (1 failure)
-- failure 1 --
Expecting status of:
<Order{id=o-1, status=PAID, total=75.00}>
to be:
<SHIPPED>
but was:
<PAID>
at GeneratedAssertionsTest.generatedSoftAssertionsEntryPoint(GeneratedAssertionsTest.java:48)
+16
View File
@@ -0,0 +1,16 @@
# files generated into target/generated-test-sources/assertj-assertions/
lab/assertj/domain/AbstractAddressAssert.java
lab/assertj/domain/AbstractCustomerAssert.java
lab/assertj/domain/AbstractCustomerDtoAssert.java
lab/assertj/domain/AbstractOrderAssert.java
lab/assertj/domain/AbstractOrderLineAssert.java
lab/assertj/domain/AbstractOrderStatusAssert.java
lab/assertj/domain/AddressAssert.java
lab/assertj/domain/CustomerAssert.java
lab/assertj/domain/CustomerDtoAssert.java
lab/assertj/domain/OrderAssert.java
lab/assertj/domain/OrderLineAssert.java
lab/assertj/domain/OrderStatusAssert.java
lab/assertj/generated/Assertions.java
lab/assertj/generated/BddAssertions.java
lab/assertj/generated/SoftAssertions.java
+15
View File
@@ -0,0 +1,15 @@
# AbstractOrderAssert.java: annotation line, class declaration and the isPaid() method, verbatim
@javax.annotation.Generated(value="assertj-assertions-generator")
public abstract class AbstractOrderAssert<S extends AbstractOrderAssert<S, A>, A extends Order> extends AbstractObjectAssert<S, A> {
public S isPaid() {
// check that actual Order we want to make assertions on is not null.
isNotNull();
// check that property call/field access is true
if (!actual.isPaid()) {
failWithMessage("\nExpecting that actual Order is paid but is not.");
}
// return the current assertion for method chaining
return myself;
}
@@ -0,0 +1,15 @@
target/generated-test-sources/assertj-assertions/lab/assertj/domain/AbstractAddressAssert.java:[8,18] package javax.annotation does not exist
target/generated-test-sources/assertj-assertions/lab/assertj/domain/AbstractCustomerAssert.java:[10,18] package javax.annotation does not exist
target/generated-test-sources/assertj-assertions/lab/assertj/domain/AbstractCustomerDtoAssert.java:[8,18] package javax.annotation does not exist
target/generated-test-sources/assertj-assertions/lab/assertj/domain/AbstractOrderAssert.java:[10,18] package javax.annotation does not exist
target/generated-test-sources/assertj-assertions/lab/assertj/domain/AbstractOrderLineAssert.java:[8,18] package javax.annotation does not exist
target/generated-test-sources/assertj-assertions/lab/assertj/domain/AbstractOrderStatusAssert.java:[8,18] package javax.annotation does not exist
target/generated-test-sources/assertj-assertions/lab/assertj/domain/AddressAssert.java:[9,18] package javax.annotation does not exist
target/generated-test-sources/assertj-assertions/lab/assertj/domain/CustomerAssert.java:[9,18] package javax.annotation does not exist
target/generated-test-sources/assertj-assertions/lab/assertj/domain/CustomerDtoAssert.java:[9,18] package javax.annotation does not exist
target/generated-test-sources/assertj-assertions/lab/assertj/domain/OrderAssert.java:[9,18] package javax.annotation does not exist
target/generated-test-sources/assertj-assertions/lab/assertj/domain/OrderLineAssert.java:[9,18] package javax.annotation does not exist
target/generated-test-sources/assertj-assertions/lab/assertj/domain/OrderStatusAssert.java:[9,18] package javax.annotation does not exist
target/generated-test-sources/assertj-assertions/lab/assertj/generated/Assertions.java:[7,18] package javax.annotation does not exist
target/generated-test-sources/assertj-assertions/lab/assertj/generated/BddAssertions.java:[6,18] package javax.annotation does not exist
target/generated-test-sources/assertj-assertions/lab/assertj/generated/SoftAssertions.java:[6,18] package javax.annotation does not exist
@@ -0,0 +1,4 @@
assertj-core 4.0.0-M1 (milestone), same sources:
Tests run: 27, Failures: 0, Errors: 0, Skipped: 0
transcripts whose text differs from the 3.27.7 run (excluding the generator captures):
(end of list; identity hashes like Customer@73c3cd09 are ignored in the comparison)