From 4973283ae0cf035d227dd94e96bba0574f8ece6a Mon Sep 17 00:00:00 2001 From: Simon Forsberg Date: Tue, 21 Apr 2026 10:06:42 +0200 Subject: [PATCH 01/23] Add test skeleton for `TicketCommentService` with mocked dependencies --- .../services/TicketCommentServiceTest.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/test/java/org/example/alfs/services/TicketCommentServiceTest.java diff --git a/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java b/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java new file mode 100644 index 0000000..c8612e5 --- /dev/null +++ b/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java @@ -0,0 +1,28 @@ +package org.example.alfs.services; + +import org.example.alfs.mapper.TicketCommentMapper; +import org.example.alfs.repositories.TicketCommentRepository; +import org.example.alfs.repositories.TicketRepository; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import static org.junit.jupiter.api.Assertions.*; + +@DisplayName("TicketCommentService Test") +@ExtendWith(MockitoExtension.class) +class TicketCommentServiceTest { + + @Mock + TicketRepository ticketRepository; + @Mock + TicketCommentRepository ticketCommentRepository; + @Mock + TicketCommentMapper ticketCommentMapper; + + @InjectMocks + TicketCommentService ticketCommentService; + +} \ No newline at end of file From 70852d49df865edfdbca19b0ab5d05270d0139fd Mon Sep 17 00:00:00 2001 From: Simon Forsberg Date: Tue, 21 Apr 2026 10:23:44 +0200 Subject: [PATCH 02/23] Enhance `TicketCommentServiceTest` by adding `addComment` tests and utility methods for user and ticket setup --- .../services/TicketCommentServiceTest.java | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java b/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java index c8612e5..8e5bc8e 100644 --- a/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java +++ b/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java @@ -1,15 +1,28 @@ package org.example.alfs.services; +import org.example.alfs.dto.comment.CommentCreateDTO; +import org.example.alfs.dto.comment.CommentViewDTO; +import org.example.alfs.entities.Ticket; +import org.example.alfs.entities.User; +import org.example.alfs.enums.Role; +import org.example.alfs.enums.TicketStatus; import org.example.alfs.mapper.TicketCommentMapper; import org.example.alfs.repositories.TicketCommentRepository; import org.example.alfs.repositories.TicketRepository; import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import java.util.Optional; + import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; @DisplayName("TicketCommentService Test") @ExtendWith(MockitoExtension.class) @@ -25,4 +38,66 @@ class TicketCommentServiceTest { @InjectMocks TicketCommentService ticketCommentService; + private Ticket openTicketWithReporter(User reporter) { + Ticket t = new Ticket(); + t.setId(1L); + t.setStatus(TicketStatus.OPEN); + t.setReporter(reporter); + return t; + } + + private User adminUser() { + User u = new User(); + u.setId(100L); + u.setRole(Role.ADMIN); + return u; + } + + private User investigatorUser() { + User u = new User(); + u.setId(200L); + u.setRole(Role.INVESTIGATOR); + return u; + } + + private User reporterUser() { + User u = new User(); + u.setId(300L); + u.setRole(Role.REPORTER); + return u; + } + + private CommentCreateDTO dto(String message, boolean internalNote) { + CommentCreateDTO dto = new CommentCreateDTO(); + dto.setMessage(message); + dto.setInternalNote(internalNote); + return dto; + } + + @Nested + @DisplayName("addComment tests") + class AddCommentTests { + + @Test + @DisplayName("Admin can add a public comment") + void admin_canAddPublicComment() { + // Arrange + User admin = adminUser(); + Ticket ticket = openTicketWithReporter(reporterUser()); + CommentViewDTO expected = new CommentViewDTO(); + + when(ticketRepository.findById(1L)).thenReturn(Optional.of(ticket)); + when(ticketCommentRepository.save(any())).thenAnswer(i -> i.getArgument(0)); + when(ticketCommentMapper.entityToViewDTO(any())).thenReturn(expected); + + // Act + CommentViewDTO result = ticketCommentService.addComment(1L, dto("Hello", false), admin, null); + + // Assert + assertSame(expected, result); + verify(ticketCommentRepository).save(any()); + } + + } + } \ No newline at end of file From 5e14da98b28193dd8dcd075f5c5ac6a4b62339c5 Mon Sep 17 00:00:00 2001 From: Simon Forsberg Date: Tue, 21 Apr 2026 10:50:20 +0200 Subject: [PATCH 03/23] Add test for admin adding internal notes in `TicketCommentServiceTest` --- .../alfs/services/TicketCommentServiceTest.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java b/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java index 8e5bc8e..eb1ec46 100644 --- a/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java +++ b/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java @@ -98,6 +98,23 @@ void admin_canAddPublicComment() { verify(ticketCommentRepository).save(any()); } + @Test + @DisplayName("Admin can add an internal note") + void admin_canAddInternalNote() { + // Arrange + User admin = adminUser(); + Ticket ticket = openTicketWithReporter(reporterUser()); + + // Act + when(ticketRepository.findById(1L)).thenReturn(Optional.of(ticket)); + when(ticketCommentRepository.save(any())).thenAnswer(i -> i.getArgument(0)); + when(ticketCommentMapper.entityToViewDTO(any())).thenReturn(new CommentViewDTO()); + + // Assert + assertDoesNotThrow(() -> + ticketCommentService.addComment(1L, dto("Internal", true), admin, null)); + } + } } \ No newline at end of file From d733b764f7dfc1e4ce39f3a5ca169e803370a702 Mon Sep 17 00:00:00 2001 From: Simon Forsberg Date: Tue, 21 Apr 2026 10:52:49 +0200 Subject: [PATCH 04/23] Add test for investigator adding a comment in `TicketCommentServiceTest` --- .../services/TicketCommentServiceTest.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java b/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java index eb1ec46..b91583a 100644 --- a/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java +++ b/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java @@ -115,6 +115,24 @@ void admin_canAddInternalNote() { ticketCommentService.addComment(1L, dto("Internal", true), admin, null)); } + @Test + @DisplayName("Assigned investigator can add a comment") + void assignedInvestigator_canAddComment() { + // Arrange + User investigator = investigatorUser(); + Ticket ticket = openTicketWithReporter(reporterUser()); + ticket.setInvestigator(investigator); + + // Act + when(ticketRepository.findById(1L)).thenReturn(Optional.of(ticket)); + when(ticketCommentRepository.save(any())).thenAnswer(i -> i.getArgument(0)); + when(ticketCommentMapper.entityToViewDTO(any())).thenReturn(new CommentViewDTO()); + + // Assert + assertDoesNotThrow(() -> + ticketCommentService.addComment(1L, dto("Note", false), investigator, null)); + } + } } \ No newline at end of file From 9d90b0129a85952a001ff62ff36131be7449750e Mon Sep 17 00:00:00 2001 From: Simon Forsberg Date: Tue, 21 Apr 2026 10:53:44 +0200 Subject: [PATCH 05/23] Add test for assigned investigator adding an internal note in `TicketCommentServiceTest` --- .../services/TicketCommentServiceTest.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java b/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java index b91583a..1822157 100644 --- a/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java +++ b/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java @@ -133,6 +133,24 @@ void assignedInvestigator_canAddComment() { ticketCommentService.addComment(1L, dto("Note", false), investigator, null)); } + @Test + @DisplayName("Assigned investigator can add an internal note") + void assignedInvestigator_canAddInternalNote() { + // Arrange + User investigator = investigatorUser(); + Ticket ticket = openTicketWithReporter(reporterUser()); + ticket.setInvestigator(investigator); + + // Act + when(ticketRepository.findById(1L)).thenReturn(Optional.of(ticket)); + when(ticketCommentRepository.save(any())).thenAnswer(i -> i.getArgument(0)); + when(ticketCommentMapper.entityToViewDTO(any())).thenReturn(new CommentViewDTO()); + + // Assert + assertDoesNotThrow(() -> + ticketCommentService.addComment(1L, dto("Internal", true), investigator, null)); + } + } } \ No newline at end of file From 6c50e082805c4602688383d25df7535f5fc3d8a6 Mon Sep 17 00:00:00 2001 From: Simon Forsberg Date: Tue, 21 Apr 2026 10:56:07 +0200 Subject: [PATCH 06/23] Add test for unassigned investigator forbidden access in `TicketCommentServiceTest` --- .../services/TicketCommentServiceTest.java | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java b/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java index 1822157..ecaddd1 100644 --- a/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java +++ b/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java @@ -16,13 +16,14 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.http.HttpStatus; +import org.springframework.web.server.ResponseStatusException; import java.util.Optional; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; +import static org.mockito.Mockito.*; @DisplayName("TicketCommentService Test") @ExtendWith(MockitoExtension.class) @@ -151,6 +152,24 @@ void assignedInvestigator_canAddInternalNote() { ticketCommentService.addComment(1L, dto("Internal", true), investigator, null)); } + @Test + @DisplayName("Unassigned investigator should be forbidden") + void unassignedInvestigator_shouldThrowForbidden() { + // Arrange + User investigator = investigatorUser(); + Ticket ticket = openTicketWithReporter(reporterUser()); + + when(ticketRepository.findById(1L)).thenReturn(Optional.of(ticket)); + + // Act + ResponseStatusException ex = assertThrows(ResponseStatusException.class, () -> + ticketCommentService.addComment(1L, dto("Note", false), investigator, null)); + + // Assert + assertEquals(HttpStatus.FORBIDDEN, ex.getStatusCode()); + verify(ticketCommentRepository, never()).save(any()); + } + } } \ No newline at end of file From 73d72c8c185a1c7d4d15abc485896c1c70203ea2 Mon Sep 17 00:00:00 2001 From: Simon Forsberg Date: Tue, 21 Apr 2026 10:57:41 +0200 Subject: [PATCH 07/23] Add test for reporter adding a comment in `TicketCommentServiceTest` --- .../alfs/services/TicketCommentServiceTest.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java b/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java index ecaddd1..ac1ef35 100644 --- a/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java +++ b/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java @@ -170,6 +170,22 @@ void unassignedInvestigator_shouldThrowForbidden() { verify(ticketCommentRepository, never()).save(any()); } + @Test + @DisplayName("Reporter who owns the ticket can add a comment") + void owningReporter_canAddComment() { + // Arrange + User reporter = reporterUser(); + Ticket ticket = openTicketWithReporter(reporter); + + when(ticketRepository.findById(1L)).thenReturn(Optional.of(ticket)); + when(ticketCommentRepository.save(any())).thenAnswer(i -> i.getArgument(0)); + when(ticketCommentMapper.entityToViewDTO(any())).thenReturn(new CommentViewDTO()); + + // Act + Assert + assertDoesNotThrow(() -> + ticketCommentService.addComment(1L, dto("My comment", false), reporter, null)); + } + } } \ No newline at end of file From 0ae624cd5b422c720f19837225055c3d4a6f2782 Mon Sep 17 00:00:00 2001 From: Simon Forsberg Date: Tue, 21 Apr 2026 10:59:20 +0200 Subject: [PATCH 08/23] Add test for reporter forbidden from creating internal notes in `TicketCommentServiceTest` --- .../services/TicketCommentServiceTest.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java b/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java index ac1ef35..4d206b7 100644 --- a/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java +++ b/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java @@ -186,6 +186,24 @@ void owningReporter_canAddComment() { ticketCommentService.addComment(1L, dto("My comment", false), reporter, null)); } + @Test + @DisplayName("Reporter cannot create an internal note") + void reporter_cannotCreateInternalNote() { + // Arrange + User reporter = reporterUser(); + Ticket ticket = openTicketWithReporter(reporter); + + when(ticketRepository.findById(1L)).thenReturn(Optional.of(ticket)); + + // Act + ResponseStatusException ex = assertThrows(ResponseStatusException.class, () -> + ticketCommentService.addComment(1L, dto("Secret", true), reporter, null)); + + // Assert + assertEquals(HttpStatus.FORBIDDEN, ex.getStatusCode()); + verify(ticketCommentRepository, never()).save(any()); + } + } } \ No newline at end of file From d93398667c440a700a0d6ba07391f6bfb5b77f51 Mon Sep 17 00:00:00 2001 From: Simon Forsberg Date: Tue, 21 Apr 2026 11:01:55 +0200 Subject: [PATCH 09/23] Add test for non-owning reporter forbidden from adding comments in `TicketCommentServiceTest` --- .../services/TicketCommentServiceTest.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java b/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java index 4d206b7..bc2f435 100644 --- a/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java +++ b/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java @@ -204,6 +204,29 @@ void reporter_cannotCreateInternalNote() { verify(ticketCommentRepository, never()).save(any()); } + @Test + @DisplayName("Reporter who does not own the ticket should be forbidden") + void nonOwningReporter_shouldThrowForbidden() { + // Arrange + User reporter = reporterUser(); + + User otherReporter = new User(); + otherReporter.setId(301L); + otherReporter.setRole(Role.REPORTER); + + Ticket ticket = openTicketWithReporter(otherReporter); + + when(ticketRepository.findById(1L)).thenReturn(Optional.of(ticket)); + + // Act + ResponseStatusException ex = assertThrows(ResponseStatusException.class, () -> + ticketCommentService.addComment(1L, dto("Note", false), reporter, null)); + + // Assert + assertEquals(HttpStatus.FORBIDDEN, ex.getStatusCode()); + verify(ticketCommentRepository, never()).save(any()); + } + } } \ No newline at end of file From c92e640e1c8cec5e42e57aa226f4d8ad482faf0c Mon Sep 17 00:00:00 2001 From: Simon Forsberg Date: Tue, 21 Apr 2026 11:03:58 +0200 Subject: [PATCH 10/23] Add test for anonymous user with valid token adding a comment in `TicketCommentServiceTest` --- .../services/TicketCommentServiceTest.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java b/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java index bc2f435..c261a78 100644 --- a/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java +++ b/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java @@ -68,6 +68,14 @@ private User reporterUser() { return u; } + private Ticket anonymousTicket(String token) { + Ticket t = new Ticket(); + t.setId(400L); + t.setStatus(TicketStatus.OPEN); + t.setReporterToken(token); + return t; + } + private CommentCreateDTO dto(String message, boolean internalNote) { CommentCreateDTO dto = new CommentCreateDTO(); dto.setMessage(message); @@ -227,6 +235,22 @@ void nonOwningReporter_shouldThrowForbidden() { verify(ticketCommentRepository, never()).save(any()); } + @Test + @DisplayName("Anonymous user with valid token can add a comment") + void anonymous_withValidToken_canAddComment() { + // Arrange + String token = "valid-token"; + Ticket ticket = anonymousTicket(token); + + when(ticketRepository.findById(1L)).thenReturn(Optional.of(ticket)); + when(ticketCommentRepository.save(any())).thenAnswer(i -> i.getArgument(0)); + when(ticketCommentMapper.entityToViewDTO(any())).thenReturn(new CommentViewDTO()); + + // Act + Assert + assertDoesNotThrow(() -> + ticketCommentService.addComment(1L, dto("Anonymous comment", false), null, token)); + } + } } \ No newline at end of file From d0cede79a5b3efac5f8c48a1aaabe735becea751 Mon Sep 17 00:00:00 2001 From: Simon Forsberg Date: Tue, 21 Apr 2026 11:05:14 +0200 Subject: [PATCH 11/23] Add test for anonymous user forbidden from creating internal notes in `TicketCommentServiceTest` --- .../services/TicketCommentServiceTest.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java b/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java index c261a78..520b039 100644 --- a/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java +++ b/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java @@ -251,6 +251,24 @@ void anonymous_withValidToken_canAddComment() { ticketCommentService.addComment(1L, dto("Anonymous comment", false), null, token)); } + @Test + @DisplayName("Anonymous user cannot create an internal note") + void anonymous_cannotCreateInternalNote() { + // Arrange + String token = "valid-token"; + Ticket ticket = anonymousTicket(token); + + when(ticketRepository.findById(1L)).thenReturn(Optional.of(ticket)); + + // Act + ResponseStatusException ex = assertThrows(ResponseStatusException.class, () -> + ticketCommentService.addComment(1L, dto("Secret", true), null, token)); + + // Assert + assertEquals(HttpStatus.FORBIDDEN, ex.getStatusCode()); + verify(ticketCommentRepository, never()).save(any()); + } + } } \ No newline at end of file From d542c4a6106dfc43240f232085a67cd6bc807be4 Mon Sep 17 00:00:00 2001 From: Simon Forsberg Date: Tue, 21 Apr 2026 11:08:46 +0200 Subject: [PATCH 12/23] Add tests for anonymous user forbidden with wrong or missing token in `TicketCommentServiceTest` --- .../services/TicketCommentServiceTest.java | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java b/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java index 520b039..0649f1e 100644 --- a/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java +++ b/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java @@ -269,6 +269,39 @@ void anonymous_cannotCreateInternalNote() { verify(ticketCommentRepository, never()).save(any()); } + @Test + @DisplayName("Anonymous user with wrong token should be forbidden") + void anonymous_withWrongToken_shouldThrowForbidden() { + // Arrange + Ticket ticket = anonymousTicket("correct-token"); + + when(ticketRepository.findById(1L)).thenReturn(Optional.of(ticket)); + + // Act + ResponseStatusException ex = assertThrows(ResponseStatusException.class, () -> + ticketCommentService.addComment(1L, dto("Note", false), null, "wrong-token")); + + // Assert + assertEquals(HttpStatus.FORBIDDEN, ex.getStatusCode()); + verify(ticketCommentRepository, never()).save(any()); + } + + @Test + @DisplayName("Anonymous user with no token should be forbidden") + void anonymous_withNoToken_shouldThrowForbidden() { + // Arrange + Ticket ticket = anonymousTicket("valid-token"); + + when(ticketRepository.findById(1L)).thenReturn(Optional.of(ticket)); + + // Act + ResponseStatusException ex = assertThrows(ResponseStatusException.class, () -> + ticketCommentService.addComment(1L, dto("Note", false), null, null)); + + // Assert + assertEquals(HttpStatus.FORBIDDEN, ex.getStatusCode()); + } + } } \ No newline at end of file From 16022b906e31f474580219d74c70e6738c01c56a Mon Sep 17 00:00:00 2001 From: Simon Forsberg Date: Tue, 21 Apr 2026 11:16:20 +0200 Subject: [PATCH 13/23] Add test for Not Found exception when ticket is missing in `TicketCommentServiceTest` --- .../alfs/services/TicketCommentServiceTest.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java b/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java index 0649f1e..45eb971 100644 --- a/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java +++ b/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java @@ -302,6 +302,21 @@ void anonymous_withNoToken_shouldThrowForbidden() { assertEquals(HttpStatus.FORBIDDEN, ex.getStatusCode()); } + @Test + @DisplayName("Should throw Not Found when ticket does not exist") + void addComment_ticketNotFound_shouldThrowNotFound() { + // Arrange + when(ticketRepository.findById(1L)).thenReturn(Optional.empty()); + + // Act + ResponseStatusException ex = assertThrows(ResponseStatusException.class, () -> + ticketCommentService.addComment(1L, dto("Hello", false), adminUser(), null)); + + // Assert + assertEquals(HttpStatus.NOT_FOUND, ex.getStatusCode()); + verify(ticketCommentRepository, never()).save(any()); + } + } } \ No newline at end of file From fb9af01e1c9b2cf531726f013a64f1016d1f2096 Mon Sep 17 00:00:00 2001 From: Simon Forsberg Date: Tue, 21 Apr 2026 11:17:41 +0200 Subject: [PATCH 14/23] Add test for admin viewing all comments in `TicketCommentServiceTest` --- .../services/TicketCommentServiceTest.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java b/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java index 45eb971..cca56b0 100644 --- a/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java +++ b/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java @@ -19,6 +19,7 @@ import org.springframework.http.HttpStatus; import org.springframework.web.server.ResponseStatusException; +import java.util.List; import java.util.Optional; import static org.junit.jupiter.api.Assertions.*; @@ -319,4 +320,27 @@ void addComment_ticketNotFound_shouldThrowNotFound() { } + @Nested + @DisplayName("getComments tests") + class GetCommentsTests { + + @Test + @DisplayName("Admin sees all comments including internal notes") + void admin_seesAllComments() { + // Arrange + User admin = adminUser(); + Ticket ticket = openTicketWithReporter(reporterUser()); + + when(ticketRepository.findById(1L)).thenReturn(Optional.of(ticket)); + when(ticketCommentRepository.findByTicketIdOrderByCreatedAtAsc(1L)).thenReturn(List.of()); + + // Act + ticketCommentService.getComments(1L, admin, null); + + // Assert + verify(ticketCommentRepository).findByTicketIdOrderByCreatedAtAsc(1L); + verify(ticketCommentRepository, never()).findByTicketIdAndInternalNoteFalseOrderByCreatedAtAsc(any()); + } + } + } \ No newline at end of file From efb987e16464d9a44ca5e57468a091da6686ee93 Mon Sep 17 00:00:00 2001 From: Simon Forsberg Date: Tue, 21 Apr 2026 11:18:42 +0200 Subject: [PATCH 15/23] Add test for assigned investigator viewing all comments in `TicketCommentServiceTest` --- .../services/TicketCommentServiceTest.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java b/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java index cca56b0..5ad3e7a 100644 --- a/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java +++ b/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java @@ -343,4 +343,23 @@ void admin_seesAllComments() { } } + @Test + @DisplayName("Assigned investigator sees all comments including internal notes") + void assignedInvestigator_seesAllComments() { + // Arrange + User investigator = investigatorUser(); + Ticket ticket = openTicketWithReporter(reporterUser()); + ticket.setInvestigator(investigator); + + when(ticketRepository.findById(1L)).thenReturn(Optional.of(ticket)); + when(ticketCommentRepository.findByTicketIdOrderByCreatedAtAsc(1L)).thenReturn(List.of()); + + // Act + ticketCommentService.getComments(1L, investigator, null); + + // Assert + verify(ticketCommentRepository).findByTicketIdOrderByCreatedAtAsc(1L); + } + + } \ No newline at end of file From 85c3c3abb174c65534078a022e9c53f76fa2881f Mon Sep 17 00:00:00 2001 From: Simon Forsberg Date: Tue, 21 Apr 2026 11:20:09 +0200 Subject: [PATCH 16/23] Add test for reporter viewing only public comments in `TicketCommentServiceTest` --- .../alfs/services/TicketCommentServiceTest.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java b/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java index 5ad3e7a..68a06ca 100644 --- a/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java +++ b/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java @@ -361,5 +361,22 @@ void assignedInvestigator_seesAllComments() { verify(ticketCommentRepository).findByTicketIdOrderByCreatedAtAsc(1L); } + @Test + @DisplayName("Reporter only sees public comments") + void reporter_seesOnlyPublicComments() { + // Arrange + User reporter = reporterUser(); + Ticket ticket = openTicketWithReporter(reporter); + + when(ticketRepository.findById(1L)).thenReturn(Optional.of(ticket)); + when(ticketCommentRepository.findByTicketIdAndInternalNoteFalseOrderByCreatedAtAsc(1L)).thenReturn(List.of()); + + // Act + ticketCommentService.getComments(1L, reporter, null); + + // Assert + verify(ticketCommentRepository).findByTicketIdAndInternalNoteFalseOrderByCreatedAtAsc(1L); + verify(ticketCommentRepository, never()).findByTicketIdOrderByCreatedAtAsc(any()); + } } \ No newline at end of file From 43abd19f7e8e6880a7e6a17b58c638619fe852b3 Mon Sep 17 00:00:00 2001 From: Simon Forsberg Date: Tue, 21 Apr 2026 11:21:07 +0200 Subject: [PATCH 17/23] Add test for anonymous user with valid token viewing only public comments in `TicketCommentServiceTest` --- .../services/TicketCommentServiceTest.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java b/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java index 68a06ca..b0d35aa 100644 --- a/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java +++ b/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java @@ -379,4 +379,22 @@ void reporter_seesOnlyPublicComments() { verify(ticketCommentRepository, never()).findByTicketIdOrderByCreatedAtAsc(any()); } + @Test + @DisplayName("Anonymous user with valid token only sees public comments") + void anonymous_withValidToken_seesOnlyPublicComments() { + // Arrange + String token = "valid-token"; + Ticket ticket = anonymousTicket(token); + + when(ticketRepository.findById(1L)).thenReturn(Optional.of(ticket)); + when(ticketCommentRepository.findByTicketIdAndInternalNoteFalseOrderByCreatedAtAsc(1L)).thenReturn(List.of()); + + // Act + ticketCommentService.getComments(1L, null, token); + + // Assert + verify(ticketCommentRepository).findByTicketIdAndInternalNoteFalseOrderByCreatedAtAsc(1L); + verify(ticketCommentRepository, never()).findByTicketIdOrderByCreatedAtAsc(any()); + } + } \ No newline at end of file From 535b87739b20951fdefe91504d1bab43cf81f3dd Mon Sep 17 00:00:00 2001 From: Simon Forsberg Date: Tue, 21 Apr 2026 11:22:09 +0200 Subject: [PATCH 18/23] Add test for anonymous user forbidden with wrong token in `TicketCommentServiceTest` --- .../alfs/services/TicketCommentServiceTest.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java b/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java index b0d35aa..fb62094 100644 --- a/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java +++ b/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java @@ -397,4 +397,20 @@ void anonymous_withValidToken_seesOnlyPublicComments() { verify(ticketCommentRepository, never()).findByTicketIdOrderByCreatedAtAsc(any()); } + @Test + @DisplayName("Anonymous user with wrong token should be forbidden") + void anonymous_withWrongToken_shouldThrowForbidden() { + // Arrange + Ticket ticket = anonymousTicket("correct-token"); + + when(ticketRepository.findById(1L)).thenReturn(Optional.of(ticket)); + + // Act + ResponseStatusException ex = assertThrows(ResponseStatusException.class, () -> + ticketCommentService.getComments(1L, null, "wrong-token")); + + // Assert + assertEquals(HttpStatus.FORBIDDEN, ex.getStatusCode()); + } + } \ No newline at end of file From a85f004b233e6276c00602c428eff46fa5f7ebbb Mon Sep 17 00:00:00 2001 From: Simon Forsberg Date: Tue, 21 Apr 2026 11:23:20 +0200 Subject: [PATCH 19/23] Refactor test names for anonymous reporter and add test for Not Found exception in `TicketCommentServiceTest` --- .../services/TicketCommentServiceTest.java | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java b/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java index fb62094..356f7fc 100644 --- a/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java +++ b/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java @@ -380,7 +380,7 @@ void reporter_seesOnlyPublicComments() { } @Test - @DisplayName("Anonymous user with valid token only sees public comments") + @DisplayName("Anonymous reporter with valid token only sees public comments") void anonymous_withValidToken_seesOnlyPublicComments() { // Arrange String token = "valid-token"; @@ -398,7 +398,7 @@ void anonymous_withValidToken_seesOnlyPublicComments() { } @Test - @DisplayName("Anonymous user with wrong token should be forbidden") + @DisplayName("Anonymous reporter with wrong token should be forbidden") void anonymous_withWrongToken_shouldThrowForbidden() { // Arrange Ticket ticket = anonymousTicket("correct-token"); @@ -413,4 +413,18 @@ void anonymous_withWrongToken_shouldThrowForbidden() { assertEquals(HttpStatus.FORBIDDEN, ex.getStatusCode()); } + @Test + @DisplayName("Should throw Not Found when ticket does not exist") + void getComments_ticketNotFound_shouldThrowNotFound() { + // Arrange + when(ticketRepository.findById(1L)).thenReturn(Optional.empty()); + + // Act + ResponseStatusException ex = assertThrows(ResponseStatusException.class, () -> + ticketCommentService.getComments(1L, adminUser(), null)); + + // Assert + assertEquals(HttpStatus.NOT_FOUND, ex.getStatusCode()); + } + } \ No newline at end of file From 0f3e2e7cfa01c08ffe82340e4697374c280f7e65 Mon Sep 17 00:00:00 2001 From: Simon Forsberg Date: Tue, 21 Apr 2026 11:24:05 +0200 Subject: [PATCH 20/23] Add test for correct mapping of comments in `TicketCommentServiceTest` --- .../services/TicketCommentServiceTest.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java b/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java index 356f7fc..554a0c0 100644 --- a/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java +++ b/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java @@ -3,6 +3,7 @@ import org.example.alfs.dto.comment.CommentCreateDTO; import org.example.alfs.dto.comment.CommentViewDTO; import org.example.alfs.entities.Ticket; +import org.example.alfs.entities.TicketComment; import org.example.alfs.entities.User; import org.example.alfs.enums.Role; import org.example.alfs.enums.TicketStatus; @@ -427,4 +428,25 @@ void getComments_ticketNotFound_shouldThrowNotFound() { assertEquals(HttpStatus.NOT_FOUND, ex.getStatusCode()); } + @Test + @DisplayName("Returned comments are mapped correctly") + void getComments_returnsMappedDTOs() { + // Arrange + User admin = adminUser(); + Ticket ticket = openTicketWithReporter(reporterUser()); + TicketComment comment = new TicketComment(); + CommentViewDTO expected = new CommentViewDTO(); + + when(ticketRepository.findById(1L)).thenReturn(Optional.of(ticket)); + when(ticketCommentRepository.findByTicketIdOrderByCreatedAtAsc(1L)).thenReturn(List.of(comment)); + when(ticketCommentMapper.entityToViewDTO(comment)).thenReturn(expected); + + // Act + List result = ticketCommentService.getComments(1L, admin, null); + + // Assert + assertEquals(1, result.size()); + assertSame(expected, result.getFirst()); + } + } \ No newline at end of file From 3763541fc09c5e52744cdaa3e6d5559073952c7c Mon Sep 17 00:00:00 2001 From: Simon Forsberg Date: Tue, 21 Apr 2026 11:26:14 +0200 Subject: [PATCH 21/23] Refactor `TicketCommentServiceTest` to improve readability by reorganizing annotations and formatting --- .../services/TicketCommentServiceTest.java | 171 +++++++++--------- 1 file changed, 85 insertions(+), 86 deletions(-) diff --git a/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java b/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java index 554a0c0..f168229 100644 --- a/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java +++ b/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java @@ -342,111 +342,110 @@ void admin_seesAllComments() { verify(ticketCommentRepository).findByTicketIdOrderByCreatedAtAsc(1L); verify(ticketCommentRepository, never()).findByTicketIdAndInternalNoteFalseOrderByCreatedAtAsc(any()); } - } - @Test - @DisplayName("Assigned investigator sees all comments including internal notes") - void assignedInvestigator_seesAllComments() { - // Arrange - User investigator = investigatorUser(); - Ticket ticket = openTicketWithReporter(reporterUser()); - ticket.setInvestigator(investigator); + @Test + @DisplayName("Assigned investigator sees all comments including internal notes") + void assignedInvestigator_seesAllComments() { + // Arrange + User investigator = investigatorUser(); + Ticket ticket = openTicketWithReporter(reporterUser()); + ticket.setInvestigator(investigator); - when(ticketRepository.findById(1L)).thenReturn(Optional.of(ticket)); - when(ticketCommentRepository.findByTicketIdOrderByCreatedAtAsc(1L)).thenReturn(List.of()); + when(ticketRepository.findById(1L)).thenReturn(Optional.of(ticket)); + when(ticketCommentRepository.findByTicketIdOrderByCreatedAtAsc(1L)).thenReturn(List.of()); - // Act - ticketCommentService.getComments(1L, investigator, null); + // Act + ticketCommentService.getComments(1L, investigator, null); - // Assert - verify(ticketCommentRepository).findByTicketIdOrderByCreatedAtAsc(1L); - } + // Assert + verify(ticketCommentRepository).findByTicketIdOrderByCreatedAtAsc(1L); + } - @Test - @DisplayName("Reporter only sees public comments") - void reporter_seesOnlyPublicComments() { - // Arrange - User reporter = reporterUser(); - Ticket ticket = openTicketWithReporter(reporter); + @Test + @DisplayName("Reporter only sees public comments") + void reporter_seesOnlyPublicComments() { + // Arrange + User reporter = reporterUser(); + Ticket ticket = openTicketWithReporter(reporter); - when(ticketRepository.findById(1L)).thenReturn(Optional.of(ticket)); - when(ticketCommentRepository.findByTicketIdAndInternalNoteFalseOrderByCreatedAtAsc(1L)).thenReturn(List.of()); + when(ticketRepository.findById(1L)).thenReturn(Optional.of(ticket)); + when(ticketCommentRepository.findByTicketIdAndInternalNoteFalseOrderByCreatedAtAsc(1L)).thenReturn(List.of()); - // Act - ticketCommentService.getComments(1L, reporter, null); + // Act + ticketCommentService.getComments(1L, reporter, null); - // Assert - verify(ticketCommentRepository).findByTicketIdAndInternalNoteFalseOrderByCreatedAtAsc(1L); - verify(ticketCommentRepository, never()).findByTicketIdOrderByCreatedAtAsc(any()); - } + // Assert + verify(ticketCommentRepository).findByTicketIdAndInternalNoteFalseOrderByCreatedAtAsc(1L); + verify(ticketCommentRepository, never()).findByTicketIdOrderByCreatedAtAsc(any()); + } - @Test - @DisplayName("Anonymous reporter with valid token only sees public comments") - void anonymous_withValidToken_seesOnlyPublicComments() { - // Arrange - String token = "valid-token"; - Ticket ticket = anonymousTicket(token); + @Test + @DisplayName("Anonymous reporter with valid token only sees public comments") + void anonymous_withValidToken_seesOnlyPublicComments() { + // Arrange + String token = "valid-token"; + Ticket ticket = anonymousTicket(token); - when(ticketRepository.findById(1L)).thenReturn(Optional.of(ticket)); - when(ticketCommentRepository.findByTicketIdAndInternalNoteFalseOrderByCreatedAtAsc(1L)).thenReturn(List.of()); + when(ticketRepository.findById(1L)).thenReturn(Optional.of(ticket)); + when(ticketCommentRepository.findByTicketIdAndInternalNoteFalseOrderByCreatedAtAsc(1L)).thenReturn(List.of()); - // Act - ticketCommentService.getComments(1L, null, token); + // Act + ticketCommentService.getComments(1L, null, token); - // Assert - verify(ticketCommentRepository).findByTicketIdAndInternalNoteFalseOrderByCreatedAtAsc(1L); - verify(ticketCommentRepository, never()).findByTicketIdOrderByCreatedAtAsc(any()); - } + // Assert + verify(ticketCommentRepository).findByTicketIdAndInternalNoteFalseOrderByCreatedAtAsc(1L); + verify(ticketCommentRepository, never()).findByTicketIdOrderByCreatedAtAsc(any()); + } - @Test - @DisplayName("Anonymous reporter with wrong token should be forbidden") - void anonymous_withWrongToken_shouldThrowForbidden() { - // Arrange - Ticket ticket = anonymousTicket("correct-token"); + @Test + @DisplayName("Anonymous reporter with wrong token should be forbidden") + void anonymous_withWrongToken_shouldThrowForbidden() { + // Arrange + Ticket ticket = anonymousTicket("correct-token"); - when(ticketRepository.findById(1L)).thenReturn(Optional.of(ticket)); + when(ticketRepository.findById(1L)).thenReturn(Optional.of(ticket)); - // Act - ResponseStatusException ex = assertThrows(ResponseStatusException.class, () -> - ticketCommentService.getComments(1L, null, "wrong-token")); + // Act + ResponseStatusException ex = assertThrows(ResponseStatusException.class, () -> + ticketCommentService.getComments(1L, null, "wrong-token")); - // Assert - assertEquals(HttpStatus.FORBIDDEN, ex.getStatusCode()); - } + // Assert + assertEquals(HttpStatus.FORBIDDEN, ex.getStatusCode()); + } - @Test - @DisplayName("Should throw Not Found when ticket does not exist") - void getComments_ticketNotFound_shouldThrowNotFound() { - // Arrange - when(ticketRepository.findById(1L)).thenReturn(Optional.empty()); + @Test + @DisplayName("Should throw Not Found when ticket does not exist") + void getComments_ticketNotFound_shouldThrowNotFound() { + // Arrange + when(ticketRepository.findById(1L)).thenReturn(Optional.empty()); - // Act - ResponseStatusException ex = assertThrows(ResponseStatusException.class, () -> - ticketCommentService.getComments(1L, adminUser(), null)); + // Act + ResponseStatusException ex = assertThrows(ResponseStatusException.class, () -> + ticketCommentService.getComments(1L, adminUser(), null)); - // Assert - assertEquals(HttpStatus.NOT_FOUND, ex.getStatusCode()); - } + // Assert + assertEquals(HttpStatus.NOT_FOUND, ex.getStatusCode()); + } - @Test - @DisplayName("Returned comments are mapped correctly") - void getComments_returnsMappedDTOs() { - // Arrange - User admin = adminUser(); - Ticket ticket = openTicketWithReporter(reporterUser()); - TicketComment comment = new TicketComment(); - CommentViewDTO expected = new CommentViewDTO(); - - when(ticketRepository.findById(1L)).thenReturn(Optional.of(ticket)); - when(ticketCommentRepository.findByTicketIdOrderByCreatedAtAsc(1L)).thenReturn(List.of(comment)); - when(ticketCommentMapper.entityToViewDTO(comment)).thenReturn(expected); - - // Act - List result = ticketCommentService.getComments(1L, admin, null); - - // Assert - assertEquals(1, result.size()); - assertSame(expected, result.getFirst()); - } + @Test + @DisplayName("Returned comments are mapped correctly") + void getComments_returnsMappedDTOs() { + // Arrange + User admin = adminUser(); + Ticket ticket = openTicketWithReporter(reporterUser()); + TicketComment comment = new TicketComment(); + CommentViewDTO expected = new CommentViewDTO(); + + when(ticketRepository.findById(1L)).thenReturn(Optional.of(ticket)); + when(ticketCommentRepository.findByTicketIdOrderByCreatedAtAsc(1L)).thenReturn(List.of(comment)); + when(ticketCommentMapper.entityToViewDTO(comment)).thenReturn(expected); + + // Act + List result = ticketCommentService.getComments(1L, admin, null); + // Assert + assertEquals(1, result.size()); + assertSame(expected, result.getFirst()); + } + } } \ No newline at end of file From c8771759d51bafe11e582d7b18f56c1e95c42a40 Mon Sep 17 00:00:00 2001 From: Simon Forsberg Date: Tue, 21 Apr 2026 11:34:39 +0200 Subject: [PATCH 22/23] Add verification that `save` is never called when anonymous user is forbidden in `TicketCommentServiceTest` --- .../java/org/example/alfs/services/TicketCommentServiceTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java b/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java index f168229..d9a168b 100644 --- a/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java +++ b/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java @@ -302,6 +302,7 @@ void anonymous_withNoToken_shouldThrowForbidden() { // Assert assertEquals(HttpStatus.FORBIDDEN, ex.getStatusCode()); + verify(ticketCommentRepository, never()).save(any()); } @Test From 49c34be63887e2666f83bfa80fd58e9d6e70966c Mon Sep 17 00:00:00 2001 From: Simon Forsberg Date: Tue, 21 Apr 2026 11:36:08 +0200 Subject: [PATCH 23/23] Combine "Act" and "Assert" sections for brevity in `TicketCommentServiceTest`. --- .../example/alfs/services/TicketCommentServiceTest.java | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java b/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java index d9a168b..3cc5ae9 100644 --- a/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java +++ b/src/test/java/org/example/alfs/services/TicketCommentServiceTest.java @@ -116,12 +116,11 @@ void admin_canAddInternalNote() { User admin = adminUser(); Ticket ticket = openTicketWithReporter(reporterUser()); - // Act when(ticketRepository.findById(1L)).thenReturn(Optional.of(ticket)); when(ticketCommentRepository.save(any())).thenAnswer(i -> i.getArgument(0)); when(ticketCommentMapper.entityToViewDTO(any())).thenReturn(new CommentViewDTO()); - // Assert + // Act + Assert assertDoesNotThrow(() -> ticketCommentService.addComment(1L, dto("Internal", true), admin, null)); } @@ -134,12 +133,11 @@ void assignedInvestigator_canAddComment() { Ticket ticket = openTicketWithReporter(reporterUser()); ticket.setInvestigator(investigator); - // Act when(ticketRepository.findById(1L)).thenReturn(Optional.of(ticket)); when(ticketCommentRepository.save(any())).thenAnswer(i -> i.getArgument(0)); when(ticketCommentMapper.entityToViewDTO(any())).thenReturn(new CommentViewDTO()); - // Assert + // Act + Assert assertDoesNotThrow(() -> ticketCommentService.addComment(1L, dto("Note", false), investigator, null)); } @@ -152,12 +150,11 @@ void assignedInvestigator_canAddInternalNote() { Ticket ticket = openTicketWithReporter(reporterUser()); ticket.setInvestigator(investigator); - // Act when(ticketRepository.findById(1L)).thenReturn(Optional.of(ticket)); when(ticketCommentRepository.save(any())).thenAnswer(i -> i.getArgument(0)); when(ticketCommentMapper.entityToViewDTO(any())).thenReturn(new CommentViewDTO()); - // Assert + // Act + Assert assertDoesNotThrow(() -> ticketCommentService.addComment(1L, dto("Internal", true), investigator, null)); }