Skip to content

Commit

Permalink
Merge pull request #772 from jqno/better-null-messages
Browse files Browse the repository at this point in the history
Improves error messages on NullPointerException
  • Loading branch information
jqno authored Feb 15, 2023
2 parents 0f8ccaa + eb9b998 commit 131b6dd
Show file tree
Hide file tree
Showing 6 changed files with 32 additions and 28 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Added

- Verifies `hashCode` consistency when `String.equalsIgnoreCase` is used. ([Issue 748](https://github.com/jqno/equalsverifier/issues/748))
- Improves error messages for detected NullPointerExceptions: if a field causes one, EqualsVerifier will indicate whether it's the field on the 'this' object or the one on the parameter object.

## [3.13.1] - 2023-02-10

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,11 @@ public void execute(
}

private void performTests(Field field, final Object reference, final Object changed) {
handle("equals", field, () -> reference.equals(changed));
handle("equals", field, () -> changed.equals(reference));
handle("equals", "the parameter's field", field, () -> reference.equals(changed));
handle("equals", "the 'this' object's field", field, () -> changed.equals(reference));
handle(
"hashCode",
"field",
field,
() -> config.getCachedHashCodeInitializer().getInitializedHashCode(changed)
);
Expand All @@ -68,11 +69,11 @@ private void performTests(Field field, final Object reference, final Object chan
value = "DCN_NULLPOINTER_EXCEPTION",
justification = "We're catching and wrapping it to provide better output to the user."
)
private void handle(String testedMethodName, Field field, Runnable r) {
private void handle(String testedMethodName, String whichOne, Field field, Runnable r) {
try {
r.run();
} catch (NullPointerException e) {
npeThrown(testedMethodName, field, e);
npeThrown(testedMethodName, whichOne, field, e);
} catch (AbstractMethodError e) {
abstractMethodErrorThrown(testedMethodName, field, e);
} catch (ClassCastException e) {
Expand All @@ -82,10 +83,11 @@ private void handle(String testedMethodName, Field field, Runnable r) {
}
}

private void npeThrown(String method, Field field, NullPointerException e) {
private void npeThrown(String method, String whichOne, Field field, NullPointerException e) {
Formatter f = Formatter.of(
"Non-nullity: %% throws NullPointerException on field %%.",
"Non-nullity: %% throws NullPointerException on %% %%.",
method,
whichOne,
field.getName()
);
fail(f, e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,16 @@ public class NullFieldsTest {
private static final String NON_NULLITY = "Non-nullity";
private static final String EQUALS = "equals throws NullPointerException";
private static final String HASHCODE = "hashCode throws NullPointerException";
private static final String ON_FIELD = "on field";
private static final String ON_THIS_FIELD = "on the 'this' object's";
private static final String ON_THE_OTHER_FIELD = "on the parameter's";

@Test
public void fail_whenEqualsThrowsNpeOnThissField() {
ExpectedException
.when(() -> EqualsVerifier.forClass(EqualsThrowsNpeOnThis.class).verify())
.assertFailure()
.assertCause(NullPointerException.class)
.assertMessageContains(NON_NULLITY, EQUALS, ON_FIELD, "color");
.assertMessageContains(NON_NULLITY, EQUALS, ON_THIS_FIELD, "color");
}

@Test
Expand All @@ -32,7 +33,7 @@ public void fail_whenEqualsThrowsNpeOnOthersField() {
.when(() -> EqualsVerifier.forClass(EqualsThrowsNpeOnOther.class).verify())
.assertFailure()
.assertCause(NullPointerException.class)
.assertMessageContains(NON_NULLITY, EQUALS, ON_FIELD, "color");
.assertMessageContains(NON_NULLITY, EQUALS, ON_THE_OTHER_FIELD, "color");
}

@Test
Expand All @@ -41,7 +42,7 @@ public void fail_whenEqualsThrowsNpeOnStaticField() {
.when(() -> EqualsVerifier.forClass(EqualsThrowsNpeOnStatic.class).verify())
.assertFailure()
.assertCause(NullPointerException.class)
.assertMessageContains(NON_NULLITY, EQUALS, ON_FIELD, "color");
.assertMessageContains(NON_NULLITY, EQUALS, ON_THE_OTHER_FIELD, "color");
}

@Test
Expand All @@ -50,7 +51,7 @@ public void fail_whenHashCodeThrowsNpe() {
.when(() -> EqualsVerifier.forClass(HashCodeThrowsNpe.class).verify())
.assertFailure()
.assertCause(NullPointerException.class)
.assertMessageContains(NON_NULLITY, HASHCODE, ON_FIELD, "color");
.assertMessageContains(NON_NULLITY, HASHCODE, "color");
}

@Test
Expand Down Expand Up @@ -84,7 +85,7 @@ public void fail_whenClassHasNullChecksForOnlySomeFields() {
.when(() -> EqualsVerifier.forClass(MixedNullFields.class).verify())
.assertFailure()
.assertCause(NullPointerException.class)
.assertMessageContains(NON_NULLITY, EQUALS, ON_FIELD, "o");
.assertMessageContains(NON_NULLITY, EQUALS, ON_THIS_FIELD, "o");
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public void fail_whenEqualsDoesntCheckForNull_givenEclipseDefaultAndNullableAnno
.assertMessageContains(
"Non-nullity",
"equals throws NullPointerException",
"on field o"
"'this' object's field o"
);
}

Expand Down Expand Up @@ -77,7 +77,7 @@ public void fail_whenEqualsDoesntCheckForNull_givenEclipseDefaultAndNullableAnno
.assertMessageContains(
"Non-nullity",
"equals throws NullPointerException",
"on field o"
"'this' object's field o"
);
}

Expand All @@ -101,7 +101,7 @@ public void fail_whenEqualsDoesntCheckForNull_givenEclipseDefaultAnnotationButIn
.assertMessageContains(
"Non-nullity",
"equals throws NullPointerException",
"on field o"
"'this' object's field o"
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public void fail_whenEqualsDoesntCheckForNull_givenFieldsHaveNonnullAnnotationBu
.assertMessageContains(
"Non-nullity",
"equals throws NullPointerException",
"on field noAnnotation"
"'this' object's field noAnnotation"
);
}

Expand Down Expand Up @@ -94,7 +94,7 @@ public void fail_whenEqualsDoesntCheckForNull_givenFindbugs1xDefaultAnnotationFo
.assertMessageContains(
"Non-nullity",
"equals throws NullPointerException",
"on field o"
"'this' object's field o"
);
}

Expand All @@ -117,7 +117,7 @@ public void fail_whenEqualsDoesntCheckForNull_givenFindbugs1xDefaultAndNullableA
.assertMessageContains(
"Non-nullity",
"equals throws NullPointerException",
"on field p"
"'this' object's field p"
);
}

Expand All @@ -131,7 +131,7 @@ public void fail_whenEqualsDoesntCheckForNull_givenFindbugs1xDefaultAndCheckForN
.assertMessageContains(
"Non-nullity",
"equals throws NullPointerException",
"on field p"
"'this' object's field p"
);
}

Expand All @@ -145,7 +145,7 @@ public void fail_whenEqualsDoesntCheckForNull_givenFindbugs1xDefaultAndNullableA
.assertMessageContains(
"Non-nullity",
"equals throws NullPointerException",
"on field p"
"'this' object's field p"
);
}

Expand All @@ -159,7 +159,7 @@ public void fail_whenEqualsDoesntCheckForNull_givenFindbugs1xDefaultAndCheckForN
.assertMessageContains(
"Non-nullity",
"equals throws NullPointerException",
"on field p"
"'this' object's field p"
);
}

Expand Down Expand Up @@ -196,7 +196,7 @@ public void fail_whenEqualsDoesntCheckForNull_givenJsr305DefaultAnnotationWithIn
.assertMessageContains(
"Non-nullity",
"equals throws NullPointerException",
"on field o"
"'this' object's field o"
);
}

Expand All @@ -218,7 +218,7 @@ public void succeed_whenEqualsDoesntCheckForNull_givenJsr305DefaultAnnotationWit
.assertMessageContains(
"Non-nullity",
"equals throws NullPointerException",
"on field o"
"'this' object's field o"
);
}

Expand All @@ -230,7 +230,7 @@ public void fail_whenEqualsDoesntCheckForNull_givenJsr305DefaultAndNullableAnnot
.assertMessageContains(
"Non-nullity",
"equals throws NullPointerException",
"on field p"
"'this' object's field p"
);
}

Expand All @@ -253,7 +253,7 @@ public void fail_whenEqualsDoesntCheckForNull_givenJsr305DefaultAndCheckForNullA
.assertMessageContains(
"Non-nullity",
"equals throws NullPointerException",
"on field p"
"'this' object's field p"
);
}

Expand All @@ -265,7 +265,7 @@ public void fail_whenEqualsDoesntCheckForNull_givenJsr305DefaultAndNullableAnnot
.assertMessageContains(
"Non-nullity",
"equals throws NullPointerException",
"on field p"
"'this' object's field p"
);
}

Expand All @@ -279,7 +279,7 @@ public void fail_whenEqualsDoesntCheckForNull_givenJsr305DefaultAndCheckForNullA
.assertMessageContains(
"Non-nullity",
"equals throws NullPointerException",
"on field p"
"'this' object's field p"
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public void fail_whenEqualsDoesntCheckForNull_givenEclipseDefaultAndNullableAnno
.assertMessageContains(
"Non-nullity",
"equals throws NullPointerException",
"on field o"
"'this' object's field o"
);
}

Expand Down

0 comments on commit 131b6dd

Please sign in to comment.