Skip to content

Commit c83c63a

Browse files
committed
Added special handling for Collection.contains(Object) throwing NullPointerException because the collection does not permit null elements.
1 parent 8c7e999 commit c83c63a

File tree

3 files changed

+59
-4
lines changed

3 files changed

+59
-4
lines changed

docs/Changelog.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ See https://github.com/cowwoc/requirements.java/commits/master for a full list.
77
* Improvements
88
* When referencing to a variable number of elements, always use the plural form of a type (e.g.
99
`actual must contain X entries` even if `X` is one).
10+
* Added special handling for `Collection.contains(Object)` throwing `NullPointerException` because the
11+
collection does not permit null elements.
1012

1113
## Version 10.0 - 2024/10/31
1214

java/src/main/java/com/github/cowwoc/requirements10/java/internal/validator/AbstractCollectionValidator.java

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,26 @@ public S contains(E expected, String name)
9595
return containsImpl(expected, name);
9696
}
9797

98+
@SuppressWarnings("PMD.AvoidCatchingNPE")
9899
private S containsImpl(E expected, String name)
99100
{
100-
if (value.validationFailed(v -> v.contains(expected)))
101+
if (value.validationFailed(v ->
102+
{
103+
try
104+
{
105+
return v.contains(expected);
106+
}
107+
catch (NullPointerException e)
108+
{
109+
if (expected == null)
110+
{
111+
// The specified element is null, and this collection does not permit null elements
112+
assert (v != null);
113+
return false;
114+
}
115+
throw e;
116+
}
117+
}))
101118
{
102119
failOnNull();
103120
addIllegalArgumentException(CollectionMessages.containsFailed(this, name, expected).toString());
@@ -119,9 +136,22 @@ public S doesNotContain(E unwanted, String name)
119136
return doesNotContainImpl(unwanted, name);
120137
}
121138

139+
@SuppressWarnings("PMD.AvoidCatchingNPE")
122140
private S doesNotContainImpl(E unwanted, String name)
123141
{
124-
if (value.validationFailed(v -> !v.contains(unwanted)))
142+
if (value.validationFailed(v ->
143+
{
144+
try
145+
{
146+
return !v.contains(unwanted);
147+
}
148+
catch (NullPointerException e)
149+
{
150+
// The specified element is null, and this collection does not permit null elements
151+
assert (v != null);
152+
return true;
153+
}
154+
}))
125155
{
126156
failOnNull();
127157
addIllegalArgumentException(

test/src/test/java/com/github/cowwoc/requirements10/test/java/CollectionTest.java

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,7 @@
1313

1414
import java.util.Arrays;
1515
import java.util.Collection;
16-
import java.util.HashMap;
1716
import java.util.List;
18-
import java.util.Map;
1917

2018
import static com.github.cowwoc.requirements10.java.TerminalEncoding.NONE;
2119

@@ -102,6 +100,20 @@ public void contains_False()
102100
}
103101
}
104102

103+
@Test
104+
public void containsNull_collectionDoesNotPermitNull()
105+
{
106+
try (ApplicationScope scope = new TestApplicationScope(NONE))
107+
{
108+
Collection<String> actual = List.of("element");
109+
List<String> expectedMessages = List.of("\"actual\" must contain null");
110+
List<String> actualMessages = new TestValidatorsImpl(scope).checkIf(actual, "actual").
111+
contains(null).elseGetFailures().getMessages();
112+
new TestValidatorsImpl(scope).requireThat(actualMessages, "actualMessages").
113+
isEqualTo(expectedMessages);
114+
}
115+
}
116+
105117
@Test
106118
public void containsVariable()
107119
{
@@ -331,6 +343,17 @@ public void doesNotContain_False()
331343
}
332344
}
333345

346+
@Test
347+
public void doesNotContainNull_collectionDoesNotPermitNull()
348+
{
349+
try (ApplicationScope scope = new TestApplicationScope(NONE))
350+
{
351+
Collection<String> actual = List.of("element");
352+
new TestValidatorsImpl(scope).requireThat(actual, "actual").
353+
doesNotContain(null);
354+
}
355+
}
356+
334357
@Test
335358
public void doesNotContainVariable()
336359
{

0 commit comments

Comments
 (0)