Add backend test suite: service unit tests, repository tests, controller slice tests #4

Closed
opened 2026-03-17 21:03:28 +01:00 by marcel · 0 comments
Owner

Goal

Establish a meaningful backend test suite covering the three layers with the highest ROI. The existing e2e tests cover the full stack — these tests fill in the gaps at the unit and slice level.


Layer 1: Service unit tests (highest priority)

Test business logic in isolation using Mockito to mock repositories.

Candidates:

  • DocumentService — search filter logic, status transitions, tag cascade delete
  • PersonService — find-or-create by alias, merge logic
  • TagService — find/create, delete cascade
  • MassImportService — import parsing, error handling, duplicate detection
  • FileService — upload/download error handling

Pattern:

@ExtendWith(MockitoExtension.class)
class DocumentServiceTest {
    @Mock DocumentRepository documentRepository;
    @InjectMocks DocumentService documentService;

    @Test
    void throwsNotFound_whenDocumentDoesNotExist() {
        when(documentRepository.findById(any())).thenReturn(Optional.empty());
        assertThatThrownBy(() -> documentService.getById(UUID.randomUUID()))
            .isInstanceOf(DomainException.class);
    }
}

Layer 2: Repository tests (@DataJpaTest)

Test non-trivial queries against a real database schema. Use Testcontainers with PostgreSQL (not H2) to stay close to production.

Candidates:

  • DocumentRepository — search query (filters by sender, receiver, tags, date range, full-text)

Layer 3: Controller slice tests (@WebMvcTest)

Test the HTTP layer with a mocked service. Focus on auth/permission enforcement and response codes — not business logic.

Candidates for each controller:

  • 401 when no session
  • 403 when insufficient permissions (@RequirePermission)
  • 400 for missing/invalid required fields
  • 200/201 happy path (response shape)

Out of scope

Full @SpringBootTest integration tests — the e2e CI job already covers the full stack.

## Goal Establish a meaningful backend test suite covering the three layers with the highest ROI. The existing e2e tests cover the full stack — these tests fill in the gaps at the unit and slice level. --- ## Layer 1: Service unit tests (highest priority) Test business logic in isolation using Mockito to mock repositories. **Candidates:** - `DocumentService` — search filter logic, status transitions, tag cascade delete - `PersonService` — find-or-create by alias, merge logic - `TagService` — find/create, delete cascade - `MassImportService` — import parsing, error handling, duplicate detection - `FileService` — upload/download error handling **Pattern:** ```java @ExtendWith(MockitoExtension.class) class DocumentServiceTest { @Mock DocumentRepository documentRepository; @InjectMocks DocumentService documentService; @Test void throwsNotFound_whenDocumentDoesNotExist() { when(documentRepository.findById(any())).thenReturn(Optional.empty()); assertThatThrownBy(() -> documentService.getById(UUID.randomUUID())) .isInstanceOf(DomainException.class); } } ``` --- ## Layer 2: Repository tests (`@DataJpaTest`) Test non-trivial queries against a real database schema. Use Testcontainers with PostgreSQL (not H2) to stay close to production. **Candidates:** - `DocumentRepository` — search query (filters by sender, receiver, tags, date range, full-text) --- ## Layer 3: Controller slice tests (`@WebMvcTest`) Test the HTTP layer with a mocked service. Focus on auth/permission enforcement and response codes — not business logic. **Candidates for each controller:** - `401` when no session - `403` when insufficient permissions (`@RequirePermission`) - `400` for missing/invalid required fields - `200`/`201` happy path (response shape) --- ## Out of scope Full `@SpringBootTest` integration tests — the e2e CI job already covers the full stack.
marcel added the devops label 2026-03-17 21:04:22 +01:00
Sign in to join this conversation.
No Label devops
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: marcel/familienarchiv#4