diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d560f55..c843e0d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -28,13 +28,13 @@ jobs: fetch-depth: 0 - uses: actions/setup-java@v4 with: - cache: gradle distribution: temurin java-version: | 11 17 21 - - uses: gradle/actions/wrapper-validation@v3 + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 - name: Build with Java ${{ matrix.java }} run: ./gradlew build --info --warning-mode=summary -PjavaVersion=${{ matrix.java }} - name: Sonar analysis diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index e989101..8d4a56c 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -27,13 +27,13 @@ jobs: - uses: actions/setup-java@v4 with: - cache: gradle distribution: temurin java-version: | 11 17 - - uses: gradle/actions/wrapper-validation@v3 + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 - name: Initialize CodeQL uses: github/codeql-action/init@v3 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ccf076f..667807f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -35,7 +35,9 @@ jobs: with: distribution: "temurin" java-version: 11 - cache: "gradle" + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 - name: Build run: ./gradlew build --warning-mode all diff --git a/CHANGELOG.md b/CHANGELOG.md index f10e5bb..95f2a83 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [0.9.0] - unreleased +## [0.8.1] - 2024-09-12 + +* [#17](https://github.com/itsallcode/hamcrest-auto-matcher/pull/17): Allow using `null` as expected value + ## [0.8.0] - 2024-09-01 ### Changes diff --git a/README.md b/README.md index 70c089d..8e9d690 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ repositories { } dependencies { - testImplementation 'org.itsallcode:hamcrest-auto-matcher:0.8.0' + testImplementation 'org.itsallcode:hamcrest-auto-matcher:0.8.1' } ``` @@ -43,7 +43,7 @@ dependencies { org.itsallcode hamcrest-auto-matcher - 0.8.0 + 0.8.1 test ``` diff --git a/build.gradle b/build.gradle index 18b899a..d2d97df 100644 --- a/build.gradle +++ b/build.gradle @@ -9,7 +9,7 @@ plugins { } group 'org.itsallcode' -version = '0.8.0' +version = '0.8.1' dependencies { api 'org.hamcrest:hamcrest:3.0' diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 9355b41..0aaefbc 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/src/main/java/org/itsallcode/matcher/auto/AutoConfigBuilder.java b/src/main/java/org/itsallcode/matcher/auto/AutoConfigBuilder.java index 120eedb..2ccb8f2 100644 --- a/src/main/java/org/itsallcode/matcher/auto/AutoConfigBuilder.java +++ b/src/main/java/org/itsallcode/matcher/auto/AutoConfigBuilder.java @@ -65,7 +65,11 @@ MatcherConfig build() { return configBuilder.build(); } + @SuppressWarnings("unchecked") static Matcher createEqualToMatcher(final T expected) { + if (expected == null) { + return (Matcher) Matchers.nullValue(); + } final Class type = expected.getClass(); if (type.isArray()) { return createArrayMatcher(expected); diff --git a/src/test/java/org/itsallcode/matcher/auto/AutoMatcherArrayTest.java b/src/test/java/org/itsallcode/matcher/auto/AutoMatcherArrayTest.java index 64d3dde..3b0c22a 100644 --- a/src/test/java/org/itsallcode/matcher/auto/AutoMatcherArrayTest.java +++ b/src/test/java/org/itsallcode/matcher/auto/AutoMatcherArrayTest.java @@ -97,6 +97,16 @@ void testStringArrayEmpty() { assertValuesDoNotMatch(new String[] { "a" }, new String[0]); } + @Test + void testObjectArrayEmpty() { + assertValuesDoNotMatch(new Object[] { "a" }, new Object[0]); + } + + @Test + void testObjectArrayMixed() { + assertValuesDoNotMatch(new Object[] { "a", null, 1 }, new Object[0]); + } + @Test void testComplexObjectArrayMatch() { assertValuesMatch(new ArrayElement[] { new ArrayElement(1, "a") }, diff --git a/src/test/java/org/itsallcode/matcher/auto/AutoMatcherListTest.java b/src/test/java/org/itsallcode/matcher/auto/AutoMatcherListTest.java index 46ffd52..8209ca7 100644 --- a/src/test/java/org/itsallcode/matcher/auto/AutoMatcherListTest.java +++ b/src/test/java/org/itsallcode/matcher/auto/AutoMatcherListTest.java @@ -6,8 +6,7 @@ import static org.itsallcode.matcher.auto.TestUtil.assertValuesDoNotMatch; import static org.itsallcode.matcher.auto.TestUtil.assertValuesMatch; -import java.util.ArrayList; -import java.util.LinkedList; +import java.util.*; import org.itsallcode.matcher.model.DemoAttribute; import org.junit.jupiter.api.Test; @@ -24,6 +23,11 @@ void testIncompatibleMemberTypes() { assertValuesDoNotMatch(asList("string"), asList(1)); } + @Test + void testActualNull() { + assertValuesDoNotMatch(asList((String) null), asList("not null")); + } + @Test void testIncompatibleMemberTypesComplexTypes() { assertValuesDoNotMatch(asList(new DemoAttribute("attr")), asList(1)); @@ -67,4 +71,20 @@ void testAsListAndNewArrayListWith1Entry() { list.add("value1"); assertValuesMatch(asList("value1"), list); } + + @Test + void testListOfAndNewArrayListWith1Entry() { + final ArrayList list = new ArrayList<>(); + list.add("value1"); + assertValuesMatch(List.of("value1"), list); + } + + @Test + void testListWithMultipleEntries() { + final ArrayList list = new ArrayList<>(); + list.add("value1"); + list.add(null); + list.add("value2"); + assertValuesMatch(asList("value1", null, "value2"), list); + } } diff --git a/src/test/java/org/itsallcode/matcher/auto/AutoMatcherMapTest.java b/src/test/java/org/itsallcode/matcher/auto/AutoMatcherMapTest.java index 72eb5a7..d4e1bf4 100644 --- a/src/test/java/org/itsallcode/matcher/auto/AutoMatcherMapTest.java +++ b/src/test/java/org/itsallcode/matcher/auto/AutoMatcherMapTest.java @@ -33,6 +33,10 @@ void testSingletonMap() { assertValuesDoNotMatch(singletonMap("key1", "value1"), singletonMap("key2", "value2")); } + @Test + void testSingletonMapAndEmptyMapOf() { + assertValuesDoNotMatch(singletonMap("key1", "value1"), Map.of()); + } @Test void testSingletonMapAndEmptyMap() { assertValuesDoNotMatch(singletonMap("key1", "value1"), emptyMap()); @@ -43,6 +47,11 @@ void testSingletonMapAndNewHashMap() { assertValuesDoNotMatch(singletonMap("key1", "value1"), new HashMap<>()); } + @Test + void testMapWithNullEntry() { + assertValuesDoNotMatch(singletonMap("key1", null), new HashMap<>()); + } + @Test void testIncompatibleTypesClassNotPublic() { final List actual = singletonList("value1"); @@ -57,10 +66,17 @@ void testAutoMatcherWorksForSingletonMapAndNewHashMapWith1Entry() { assertValuesMatch(singletonMap("key1", "value1"), map); } + @Test + void testHashMapWithNullEntry() { + final HashMap map = new HashMap<>(); + map.put("key1", null); + assertValuesMatch(singletonMap("key1", null), map); + } + @Test void testSingletonMapAndNewHashMapWith1Entry() { final HashMap map = new HashMap<>(); map.put("key1", "value1"); - assertValuesMatch(singletonMap("key1", "value1"), map); + assertValuesMatch(Map.of("key1", "value1"), map); } } diff --git a/src/test/java/org/itsallcode/matcher/auto/AutoMatcherTest.java b/src/test/java/org/itsallcode/matcher/auto/AutoMatcherTest.java index 6b6bfd7..1889a74 100644 --- a/src/test/java/org/itsallcode/matcher/auto/AutoMatcherTest.java +++ b/src/test/java/org/itsallcode/matcher/auto/AutoMatcherTest.java @@ -41,6 +41,16 @@ void setup() { value2Equal = model("m", 2); } + @Test + void testNull() { + assertThat(null, AutoMatcher.equalTo(null)); + } + + @Test + void testNotNull() { + assertThat("null", not(AutoMatcher.equalTo(null))); + } + @Test @SuppressWarnings("unchecked") void testIncompatibleTypes() { @@ -81,11 +91,6 @@ void testEqualToNotEqual() { assertThat(value1, not(AutoMatcher.equalTo(value2))); } - @Test - void testEqualToNullThrowsNullPointerException() { - assertThrows(NullPointerException.class, () -> AutoMatcher.equalTo(null)); - } - @Test void testContainsActualEmptyListSuccess() { assertThat(emptyList(), AutoMatcher.contains()); diff --git a/src/test/java/org/itsallcode/matcher/test/MatcherTestBase.java b/src/test/java/org/itsallcode/matcher/test/MatcherTestBase.java index d318287..e929bba 100644 --- a/src/test/java/org/itsallcode/matcher/test/MatcherTestBase.java +++ b/src/test/java/org/itsallcode/matcher/test/MatcherTestBase.java @@ -21,11 +21,6 @@ public abstract class MatcherTestBase { protected abstract Function> createNewSUT(); - @Test - void testNullObject() { - assertThrows(NullPointerException.class, () -> createMatcher(null)); - } - @Test void subjectUnderTestMustBeNotNull() { assertNotNull(createNewSUT());