test(document): collapse all-null SearchFilters literals to noFilters() (#683)

Replace the ~29 repeated `new SearchFilters(null, null, null, null, null,
null, null, null, null, false)` literals across the search test suites with
a shared SearchFiltersFixtures.noFilters() factory (and noFilters()
.withUndated(true) for the undated-only case). Tests that pin a specific
field keep their explicit `new SearchFilters(...)` so intent stays visible.
Pure test-ergonomics cleanup raised in the #702 review; no behaviour change.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-05-31 15:53:34 +02:00
parent dcb57ffacd
commit 4c2f036de0
5 changed files with 52 additions and 31 deletions

View File

@@ -24,6 +24,7 @@ import java.util.Set;
import java.util.UUID; import java.util.UUID;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.raddatz.familienarchiv.document.SearchFiltersFixtures.noFilters;
import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.Assertions.assertThatCode;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
@@ -122,7 +123,7 @@ class DocumentLazyLoadingTest {
savedDocument("SrDoc", "sr_doc.pdf", sender, Set.of(receiver), Set.of(tag)); savedDocument("SrDoc", "sr_doc.pdf", sender, Set.of(receiver), Set.of(tag));
DocumentSearchResult result = documentService.searchDocuments( DocumentSearchResult result = documentService.searchDocuments(
new SearchFilters(null, null, null, null, null, null, null, null, null, false), noFilters(),
DocumentSort.RECEIVER, "asc", PageRequest.of(0, 20)); DocumentSort.RECEIVER, "asc", PageRequest.of(0, 20));
assertThat(result.totalElements()).isGreaterThan(0); assertThat(result.totalElements()).isGreaterThan(0);
assertThatCode(() -> assertThatCode(() ->
@@ -137,7 +138,7 @@ class DocumentLazyLoadingTest {
savedDocument("SsDoc", "ss_doc.pdf", sender, Set.of(), Set.of(tag)); savedDocument("SsDoc", "ss_doc.pdf", sender, Set.of(), Set.of(tag));
assertThatCode(() -> documentService.searchDocuments( assertThatCode(() -> documentService.searchDocuments(
new SearchFilters(null, null, null, null, null, null, null, null, null, false), noFilters(),
DocumentSort.SENDER, "asc", PageRequest.of(0, 20))) DocumentSort.SENDER, "asc", PageRequest.of(0, 20)))
.doesNotThrowAnyException(); .doesNotThrowAnyException();
} }

View File

@@ -17,6 +17,7 @@ import java.util.HashSet;
import java.util.Set; import java.util.Set;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.raddatz.familienarchiv.document.SearchFiltersFixtures.noFilters;
import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.Assertions.assertThatCode;
/** /**
@@ -55,7 +56,7 @@ class DocumentListItemIntegrationTest {
.build()); .build());
assertThatCode(() -> documentService.searchDocuments( assertThatCode(() -> documentService.searchDocuments(
new SearchFilters(null, null, null, null, null, null, null, null, null, false), noFilters(),
DocumentSort.DATE, "DESC", PageRequest.of(0, 50))) DocumentSort.DATE, "DESC", PageRequest.of(0, 50)))
.doesNotThrowAnyException(); .doesNotThrowAnyException();
} }
@@ -70,7 +71,7 @@ class DocumentListItemIntegrationTest {
.build()); .build());
DocumentSearchResult result = documentService.searchDocuments( DocumentSearchResult result = documentService.searchDocuments(
new SearchFilters(null, null, null, null, null, null, null, null, null, false), noFilters(),
DocumentSort.DATE, "DESC", PageRequest.of(0, 50)); DocumentSort.DATE, "DESC", PageRequest.of(0, 50));
assertThat(result.totalElements()).isGreaterThan(0); assertThat(result.totalElements()).isGreaterThan(0);
@@ -91,7 +92,7 @@ class DocumentListItemIntegrationTest {
.build()); .build());
DocumentSearchResult result = documentService.searchDocuments( DocumentSearchResult result = documentService.searchDocuments(
new SearchFilters(null, null, null, null, null, null, null, null, null, false), noFilters(),
DocumentSort.DATE, "DESC", PageRequest.of(0, 50)); DocumentSort.DATE, "DESC", PageRequest.of(0, 50));
DocumentListItem item = result.items().stream() DocumentListItem item = result.items().stream()

View File

@@ -21,6 +21,7 @@ import java.time.LocalDate;
import java.util.UUID; import java.util.UUID;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.raddatz.familienarchiv.document.SearchFiltersFixtures.noFilters;
/** /**
* End-to-end paged search test with real PostgreSQL (Testcontainers). Covers the * End-to-end paged search test with real PostgreSQL (Testcontainers). Covers the
@@ -61,7 +62,7 @@ class DocumentSearchPagedIntegrationTest {
@Test @Test
void search_firstPage_returnsExactlyPageSizeItems_andCorrectTotalElements() { void search_firstPage_returnsExactlyPageSizeItems_andCorrectTotalElements() {
DocumentSearchResult result = documentService.searchDocuments( DocumentSearchResult result = documentService.searchDocuments(
new SearchFilters(null, null, null, null, null, null, null, null, null, false), noFilters(),
DocumentSort.DATE, "DESC", PageRequest.of(0, 50)); DocumentSort.DATE, "DESC", PageRequest.of(0, 50));
assertThat(result.items()).hasSize(50); assertThat(result.items()).hasSize(50);
@@ -74,7 +75,7 @@ class DocumentSearchPagedIntegrationTest {
@Test @Test
void search_lastPartialPage_returnsRemainingItems() { void search_lastPartialPage_returnsRemainingItems() {
DocumentSearchResult result = documentService.searchDocuments( DocumentSearchResult result = documentService.searchDocuments(
new SearchFilters(null, null, null, null, null, null, null, null, null, false), noFilters(),
DocumentSort.DATE, "DESC", PageRequest.of(2, 50)); DocumentSort.DATE, "DESC", PageRequest.of(2, 50));
// Page 2 (offset 100) of 120 docs → exactly 20 items on the tail. // Page 2 (offset 100) of 120 docs → exactly 20 items on the tail.
@@ -86,7 +87,7 @@ class DocumentSearchPagedIntegrationTest {
@Test @Test
void search_pageBeyondLast_returnsEmptyContent_totalElementsStillCorrect() { void search_pageBeyondLast_returnsEmptyContent_totalElementsStillCorrect() {
DocumentSearchResult result = documentService.searchDocuments( DocumentSearchResult result = documentService.searchDocuments(
new SearchFilters(null, null, null, null, null, null, null, null, null, false), noFilters(),
DocumentSort.DATE, "DESC", PageRequest.of(99, 50)); DocumentSort.DATE, "DESC", PageRequest.of(99, 50));
assertThat(result.items()).isEmpty(); assertThat(result.items()).isEmpty();
@@ -99,7 +100,7 @@ class DocumentSearchPagedIntegrationTest {
// comment in DocumentService). Proves that the in-memory slice path // comment in DocumentService). Proves that the in-memory slice path
// returns the correct total from a real repository fetch. // returns the correct total from a real repository fetch.
DocumentSearchResult result = documentService.searchDocuments( DocumentSearchResult result = documentService.searchDocuments(
new SearchFilters(null, null, null, null, null, null, null, null, null, false), noFilters(),
DocumentSort.SENDER, "asc", PageRequest.of(1, 50)); DocumentSort.SENDER, "asc", PageRequest.of(1, 50));
assertThat(result.items()).hasSize(50); assertThat(result.items()).hasSize(50);
@@ -125,7 +126,7 @@ class DocumentSearchPagedIntegrationTest {
} }
DocumentSearchResult result = documentService.searchDocuments( DocumentSearchResult result = documentService.searchDocuments(
new SearchFilters(null, null, null, null, null, null, null, null, null, false), noFilters(),
DocumentSort.DATE, "DESC", PageRequest.of(0, 50)); DocumentSort.DATE, "DESC", PageRequest.of(0, 50));
// Global undated count is the full undated total, independent of page size. // Global undated count is the full undated total, independent of page size.
@@ -153,10 +154,10 @@ class DocumentSearchPagedIntegrationTest {
} }
DocumentSearchResult unfiltered = documentService.searchDocuments( DocumentSearchResult unfiltered = documentService.searchDocuments(
new SearchFilters(null, null, null, null, null, null, null, null, null, false), noFilters(),
DocumentSort.DATE, "DESC", PageRequest.of(0, 50)); DocumentSort.DATE, "DESC", PageRequest.of(0, 50));
DocumentSearchResult undatedOnly = documentService.searchDocuments( DocumentSearchResult undatedOnly = documentService.searchDocuments(
new SearchFilters(null, null, null, null, null, null, null, null, null, true), noFilters().withUndated(true),
DocumentSort.DATE, "DESC", PageRequest.of(0, 50)); DocumentSort.DATE, "DESC", PageRequest.of(0, 50));
assertThat(unfiltered.undatedCount()).isEqualTo(undatedTotal); assertThat(unfiltered.undatedCount()).isEqualTo(undatedTotal);
@@ -188,10 +189,10 @@ class DocumentSearchPagedIntegrationTest {
@Test @Test
void search_differentPagesReturnDisjointSlices() { void search_differentPagesReturnDisjointSlices() {
DocumentSearchResult page0 = documentService.searchDocuments( DocumentSearchResult page0 = documentService.searchDocuments(
new SearchFilters(null, null, null, null, null, null, null, null, null, false), noFilters(),
DocumentSort.DATE, "DESC", PageRequest.of(0, 50)); DocumentSort.DATE, "DESC", PageRequest.of(0, 50));
DocumentSearchResult page1 = documentService.searchDocuments( DocumentSearchResult page1 = documentService.searchDocuments(
new SearchFilters(null, null, null, null, null, null, null, null, null, false), noFilters(),
DocumentSort.DATE, "DESC", PageRequest.of(1, 50)); DocumentSort.DATE, "DESC", PageRequest.of(1, 50));
// No document id should appear on both pages — slicing must be exclusive. // No document id should appear on both pages — slicing must be exclusive.

View File

@@ -45,6 +45,7 @@ import java.util.Set;
import java.util.UUID; import java.util.UUID;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.raddatz.familienarchiv.document.SearchFiltersFixtures.noFilters;
import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyInt;
@@ -1442,7 +1443,7 @@ class DocumentServiceTest {
.thenReturn(new PageImpl<>(List.of())); .thenReturn(new PageImpl<>(List.of()));
documentService.searchDocuments( documentService.searchDocuments(
new SearchFilters(null, null, null, null, null, null, null, null, null, false), noFilters(),
org.raddatz.familienarchiv.document.DocumentSort.DATE, "DESC", org.springframework.data.domain.PageRequest.of(1, 50)); org.raddatz.familienarchiv.document.DocumentSort.DATE, "DESC", org.springframework.data.domain.PageRequest.of(1, 50));
verify(documentRepository).findAll(any(org.springframework.data.jpa.domain.Specification.class), any(Pageable.class)); verify(documentRepository).findAll(any(org.springframework.data.jpa.domain.Specification.class), any(Pageable.class));
@@ -1456,7 +1457,7 @@ class DocumentServiceTest {
.thenReturn(new PageImpl<>(List.of())); .thenReturn(new PageImpl<>(List.of()));
documentService.searchDocuments( documentService.searchDocuments(
new SearchFilters(null, null, null, null, null, null, null, null, null, false), noFilters(),
org.raddatz.familienarchiv.document.DocumentSort.DATE, "DESC", org.springframework.data.domain.PageRequest.of(3, 25)); org.raddatz.familienarchiv.document.DocumentSort.DATE, "DESC", org.springframework.data.domain.PageRequest.of(3, 25));
verify(documentRepository).findAll(any(org.springframework.data.jpa.domain.Specification.class), captor.capture()); verify(documentRepository).findAll(any(org.springframework.data.jpa.domain.Specification.class), captor.capture());
@@ -1473,7 +1474,7 @@ class DocumentServiceTest {
.thenReturn(new PageImpl<>(List.of(d), org.springframework.data.domain.PageRequest.of(0, 50), 120L)); .thenReturn(new PageImpl<>(List.of(d), org.springframework.data.domain.PageRequest.of(0, 50), 120L));
DocumentSearchResult result = documentService.searchDocuments( DocumentSearchResult result = documentService.searchDocuments(
new SearchFilters(null, null, null, null, null, null, null, null, null, false), noFilters(),
org.raddatz.familienarchiv.document.DocumentSort.DATE, "DESC", org.springframework.data.domain.PageRequest.of(0, 50)); org.raddatz.familienarchiv.document.DocumentSort.DATE, "DESC", org.springframework.data.domain.PageRequest.of(0, 50));
assertThat(result.totalElements()).isEqualTo(120L); assertThat(result.totalElements()).isEqualTo(120L);
@@ -1490,7 +1491,7 @@ class DocumentServiceTest {
.thenReturn(new PageImpl<>(List.of())); .thenReturn(new PageImpl<>(List.of()));
documentService.searchDocuments( documentService.searchDocuments(
new SearchFilters(null, null, null, null, null, null, null, null, null, false), noFilters(),
DocumentSort.DATE, "DESC", org.springframework.data.domain.PageRequest.of(0, 5)); DocumentSort.DATE, "DESC", org.springframework.data.domain.PageRequest.of(0, 5));
verify(documentRepository).findAll(any(org.springframework.data.jpa.domain.Specification.class), captor.capture()); verify(documentRepository).findAll(any(org.springframework.data.jpa.domain.Specification.class), captor.capture());
@@ -1514,7 +1515,7 @@ class DocumentServiceTest {
.thenReturn(new PageImpl<>(List.of())); .thenReturn(new PageImpl<>(List.of()));
documentService.searchDocuments( documentService.searchDocuments(
new SearchFilters(null, null, null, null, null, null, null, null, null, false), noFilters(),
DocumentSort.DATE, "ASC", org.springframework.data.domain.PageRequest.of(0, 5)); DocumentSort.DATE, "ASC", org.springframework.data.domain.PageRequest.of(0, 5));
verify(documentRepository).findAll(any(org.springframework.data.jpa.domain.Specification.class), captor.capture()); verify(documentRepository).findAll(any(org.springframework.data.jpa.domain.Specification.class), captor.capture());
@@ -1536,7 +1537,7 @@ class DocumentServiceTest {
.thenReturn(new PageImpl<>(List.of())); .thenReturn(new PageImpl<>(List.of()));
documentService.searchDocuments( documentService.searchDocuments(
new SearchFilters(null, null, null, null, null, null, null, null, null, false), noFilters(),
DocumentSort.UPDATED_AT, "DESC", org.springframework.data.domain.PageRequest.of(0, 5)); DocumentSort.UPDATED_AT, "DESC", org.springframework.data.domain.PageRequest.of(0, 5));
verify(documentRepository).findAll(any(org.springframework.data.jpa.domain.Specification.class), captor.capture()); verify(documentRepository).findAll(any(org.springframework.data.jpa.domain.Specification.class), captor.capture());
@@ -1561,7 +1562,7 @@ class DocumentServiceTest {
.thenReturn(all); .thenReturn(all);
DocumentSearchResult result = documentService.searchDocuments( DocumentSearchResult result = documentService.searchDocuments(
new SearchFilters(null, null, null, null, null, null, null, null, null, false), noFilters(),
org.raddatz.familienarchiv.document.DocumentSort.SENDER, "asc", org.springframework.data.domain.PageRequest.of(1, 50)); org.raddatz.familienarchiv.document.DocumentSort.SENDER, "asc", org.springframework.data.domain.PageRequest.of(1, 50));
assertThat(result.totalElements()).isEqualTo(120L); assertThat(result.totalElements()).isEqualTo(120L);
@@ -1586,7 +1587,7 @@ class DocumentServiceTest {
.thenReturn(all); .thenReturn(all);
DocumentSearchResult result = documentService.searchDocuments( DocumentSearchResult result = documentService.searchDocuments(
new SearchFilters(null, null, null, null, null, null, null, null, null, false), noFilters(),
org.raddatz.familienarchiv.document.DocumentSort.SENDER, "asc", org.springframework.data.domain.PageRequest.of(10, 50)); org.raddatz.familienarchiv.document.DocumentSort.SENDER, "asc", org.springframework.data.domain.PageRequest.of(10, 50));
assertThat(result.items()).isEmpty(); assertThat(result.items()).isEmpty();
@@ -1612,7 +1613,7 @@ class DocumentServiceTest {
.thenReturn(new PageImpl<>(List.of())); .thenReturn(new PageImpl<>(List.of()));
documentService.searchDocuments( documentService.searchDocuments(
new SearchFilters(null, null, null, null, null, null, null, null, null, false), null, null, UNPAGED); noFilters(), null, null, UNPAGED);
verify(documentRepository).findAll(any(org.springframework.data.jpa.domain.Specification.class), any(Pageable.class)); verify(documentRepository).findAll(any(org.springframework.data.jpa.domain.Specification.class), any(Pageable.class));
} }
@@ -1690,7 +1691,7 @@ class DocumentServiceTest {
.thenReturn(List.of(withSender, noSender)); .thenReturn(List.of(withSender, noSender));
DocumentSearchResult result = documentService.searchDocuments( DocumentSearchResult result = documentService.searchDocuments(
new SearchFilters(null, null, null, null, null, null, null, null, null, false), noFilters(),
DocumentSort.SENDER, "asc", UNPAGED); DocumentSort.SENDER, "asc", UNPAGED);
assertThat(result.items()).hasSize(2); assertThat(result.items()).hasSize(2);
@@ -1711,7 +1712,7 @@ class DocumentServiceTest {
.thenReturn(List.of(noReceivers, withReceiver)); .thenReturn(List.of(noReceivers, withReceiver));
DocumentSearchResult result = documentService.searchDocuments( DocumentSearchResult result = documentService.searchDocuments(
new SearchFilters(null, null, null, null, null, null, null, null, null, false), noFilters(),
DocumentSort.RECEIVER, "asc", UNPAGED); DocumentSort.RECEIVER, "asc", UNPAGED);
assertThat(result.items()).extracting(DocumentListItem::title) assertThat(result.items()).extracting(DocumentListItem::title)
@@ -1745,7 +1746,7 @@ class DocumentServiceTest {
.thenReturn(List.of(undatedBob, datedAnna, datedBob, undatedAnna)); .thenReturn(List.of(undatedBob, datedAnna, datedBob, undatedAnna));
DocumentSearchResult result = documentService.searchDocuments( DocumentSearchResult result = documentService.searchDocuments(
new SearchFilters(null, null, null, null, null, null, null, null, null, false), noFilters(),
DocumentSort.SENDER, "asc", UNPAGED); DocumentSort.SENDER, "asc", UNPAGED);
// Bob's group precedes Anna's group (ASC by sender). The sort is stable, so // Bob's group precedes Anna's group (ASC by sender). The sort is stable, so
@@ -1777,7 +1778,7 @@ class DocumentServiceTest {
.thenReturn(List.of(undatedBob, datedAnna, datedBob, undatedAnna)); .thenReturn(List.of(undatedBob, datedAnna, datedBob, undatedAnna));
DocumentSearchResult result = documentService.searchDocuments( DocumentSearchResult result = documentService.searchDocuments(
new SearchFilters(null, null, null, null, null, null, null, null, null, false), noFilters(),
DocumentSort.SENDER, "desc", UNPAGED); DocumentSort.SENDER, "desc", UNPAGED);
// Anna's group precedes Bob's (DESC by sender); undated stays inside its group. // Anna's group precedes Bob's (DESC by sender); undated stays inside its group.
@@ -1801,7 +1802,7 @@ class DocumentServiceTest {
.thenReturn(List.of(undatedFromAlice)); .thenReturn(List.of(undatedFromAlice));
DocumentSearchResult result = documentService.searchDocuments( DocumentSearchResult result = documentService.searchDocuments(
new SearchFilters(null, null, null, null, null, null, null, null, null, true), noFilters().withUndated(true),
DocumentSort.SENDER, "asc", UNPAGED); DocumentSort.SENDER, "asc", UNPAGED);
// The in-memory path queried via a Specification (built by buildSearchSpec with // The in-memory path queried via a Specification (built by buildSearchSpec with
@@ -1843,7 +1844,7 @@ class DocumentServiceTest {
.thenReturn(List.of(docNullName, docSmith)); .thenReturn(List.of(docNullName, docSmith));
DocumentSearchResult result = documentService.searchDocuments( DocumentSearchResult result = documentService.searchDocuments(
new SearchFilters(null, null, null, null, null, null, null, null, null, false), noFilters(),
DocumentSort.SENDER, "asc", UNPAGED); DocumentSort.SENDER, "asc", UNPAGED);
// null lastName should sort to end (treated as empty), not before "smith" (as "null") // null lastName should sort to end (treated as empty), not before "smith" (as "null")
@@ -1882,7 +1883,7 @@ class DocumentServiceTest {
.thenReturn(new PageImpl<>(List.of())); .thenReturn(new PageImpl<>(List.of()));
DocumentSearchResult result = documentService.searchDocuments( DocumentSearchResult result = documentService.searchDocuments(
new SearchFilters(null, null, null, null, null, null, null, null, null, false), noFilters(),
null, null, UNPAGED); null, null, UNPAGED);
assertThat(result.items()).isEmpty(); assertThat(result.items()).isEmpty();
@@ -2421,7 +2422,7 @@ class DocumentServiceTest {
.thenReturn(List.of(d1, d2)); .thenReturn(List.of(d1, d2));
List<UUID> result = documentService.findIdsForFilter( List<UUID> result = documentService.findIdsForFilter(
new SearchFilters(null, null, null, null, null, null, null, null, null, false)); noFilters());
assertThat(result).containsExactly(d1.getId(), d2.getId()); assertThat(result).containsExactly(d1.getId(), d2.getId());
} }

View File

@@ -0,0 +1,17 @@
package org.raddatz.familienarchiv.document;
/** Test fixtures for {@link SearchFilters}. */
final class SearchFiltersFixtures {
private SearchFiltersFixtures() {}
/**
* A {@link SearchFilters} with no predicate active — the common search-test
* baseline. Combine with {@code .withUndated(true)} for the undated-only case;
* construct {@code new SearchFilters(...)} directly when a test pins a specific
* field, so the intent stays visible at the call site.
*/
static SearchFilters noFilters() {
return new SearchFilters(null, null, null, null, null, null, null, null, null, false);
}
}