Skip to content

Add AttachmentService test suite - #39

Merged
simonforsberg merged 15 commits into
mainfrom
feature/attachmentservice-test
Apr 24, 2026
Merged

Add AttachmentService test suite#39
simonforsberg merged 15 commits into
mainfrom
feature/attachmentservice-test

Conversation

@simonforsberg

@simonforsberg simonforsberg commented Apr 22, 2026

Copy link
Copy Markdown
Contributor

@coderabbitai review

Summary by CodeRabbit

  • Tests

    • Added a comprehensive test suite for attachment upload and access control covering authenticated/anonymous uploads, token handling, filename defaults, storage cleanup on failure, and authorization outcomes.
  • Chores

    • Minor formatting and whitespace cleanups in existing test files.

@coderabbitai

coderabbitai Bot commented Apr 22, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@simonforsberg has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 46 minutes and 13 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 46 minutes and 13 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2c771022-6810-49a9-b332-da51238da897

📥 Commits

Reviewing files that changed from the base of the PR and between fd4d965 and 12e3103.

📒 Files selected for processing (1)
  • src/test/java/org/example/alfs/services/AttachmentServiceTest.java
📝 Walkthrough

Walkthrough

Added a new comprehensive JUnit 5 test suite for AttachmentService and minor whitespace formatting changes in existing test classes and one blank-line removal in AttachmentService source. Tests cover upload behavior, authorization checks, error handling, filename defaults, and storage cleanup.

Changes

Cohort / File(s) Summary
AttachmentService Source
src/main/java/org/example/alfs/services/AttachmentService.java
Removed an empty blank line between uploadToTicket(...) and checkAccess(...). No functional changes.
AttachmentService Tests
src/test/java/org/example/alfs/services/AttachmentServiceTest.java
Added new JUnit 5 test class with Mockito mocks. Nested suites UploadToTicketTest and CheckAccessTest validate successful uploads (including anonymous token flow), error responses (401/404/403), filename defaulting, and cleanup when storage save fails.
Other Test Formatting
src/test/java/org/example/alfs/services/AuthServiceTest.java, src/test/java/org/example/alfs/services/TicketServiceTest.java
Removed blank lines between @Mock field declarations for formatting consistency; no behavioral changes.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

Suggested reviewers

  • addee1
  • FionaSprinkles

Poem

🐰 I hopped through tests with Mockito cheer,
Stubbing tokens, files, and callers near.
Uploads verified, access gates alight,
Cleanup hops in if saving goes slight.
A tiny TODO nibbles at midnight.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Add AttachmentService test suite' directly and clearly summarizes the main change: introducing comprehensive test coverage for the AttachmentService class.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/attachmentservice-test

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
src/test/java/org/example/alfs/services/AttachmentServiceTest.java (1)

243-251: Align the invalid-token test name with the asserted status.

The method name says throwsUnauthorized, but Line 251 asserts HttpStatus.NOT_FOUND. Rename the test if NOT_FOUND is intentional.

🧹 Proposed naming cleanup
-        `@DisplayName`("Anonymous reporter with invalid token denied")
-        void anonymousReporter_withWrongToken_throwsUnauthorized() {
+        `@DisplayName`("Anonymous reporter with invalid token should return Not Found")
+        void anonymousReporter_withWrongToken_throwsNotFound() {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/test/java/org/example/alfs/services/AttachmentServiceTest.java` around
lines 243 - 251, The test method
anonymousReporter_withWrongToken_throwsUnauthorized has a name indicating
UNAUTHORIZED but asserts HttpStatus.NOT_FOUND; make them consistent by either
renaming the test method to reflect NOT_FOUND (e.g.,
anonymousReporter_withWrongToken_throwsNotFound) or changing the asserted status
in the assertion to HttpStatus.UNAUTHORIZED depending on intended behavior of
attachmentService.uploadToTicket; update the method name or the assertion in
AttachmentServiceTest.uploadToTicket test accordingly.
src/main/java/org/example/alfs/services/AttachmentService.java (1)

99-116: Resolve or track this TODO instead of leaving suspected dead code.

If getCurrentUserOrNull() has no usages, prefer removing the helper and the now-unused SecurityUtils dependency; otherwise, link this TODO to a tracked issue so it does not become stale.

Do you want me to draft the cleanup diff for the method, field, constructor parameter, and test mock?

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/java/org/example/alfs/services/AttachmentService.java` around lines
99 - 116, getCurrentUserOrNull() is likely dead code; search for usages of the
method and the securityUtils dependency and either (A) remove the private method
getCurrentUserOrNull(), delete the SecurityUtils field/constructor parameter and
update any tests/mocks that reference it, or (B) if it is needed later, replace
the inline TODO with a link to an open issue/track ID and add a short javadoc
explaining intended ownership (e.g., "moved-to-service #<ISSUE_ID>"). Reference
getCurrentUserOrNull, securityUtils, and SecurityUtils when making the change so
related constructor params, fields, and test mocks are cleaned up or the TODO is
tracked.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/test/java/org/example/alfs/services/AttachmentServiceTest.java`:
- Around line 80-92: The test
authenticatedReporter_withValidTicket_shouldUploadSuccessfully currently passes
admin to attachmentService.uploadToTicket, so update the call to use the
reporter test fixture instead (replace admin with reporter) so the test
exercises the reporter scenario; keep the existing mocks
(ticketRepository.findById, storageService.upload, file.getOriginalFilename) and
assertions on result.getFileName(), result.getS3Key(), and
verify(attachmentRepository).save(...) intact.

---

Nitpick comments:
In `@src/main/java/org/example/alfs/services/AttachmentService.java`:
- Around line 99-116: getCurrentUserOrNull() is likely dead code; search for
usages of the method and the securityUtils dependency and either (A) remove the
private method getCurrentUserOrNull(), delete the SecurityUtils
field/constructor parameter and update any tests/mocks that reference it, or (B)
if it is needed later, replace the inline TODO with a link to an open
issue/track ID and add a short javadoc explaining intended ownership (e.g.,
"moved-to-service #<ISSUE_ID>"). Reference getCurrentUserOrNull, securityUtils,
and SecurityUtils when making the change so related constructor params, fields,
and test mocks are cleaned up or the TODO is tracked.

In `@src/test/java/org/example/alfs/services/AttachmentServiceTest.java`:
- Around line 243-251: The test method
anonymousReporter_withWrongToken_throwsUnauthorized has a name indicating
UNAUTHORIZED but asserts HttpStatus.NOT_FOUND; make them consistent by either
renaming the test method to reflect NOT_FOUND (e.g.,
anonymousReporter_withWrongToken_throwsNotFound) or changing the asserted status
in the assertion to HttpStatus.UNAUTHORIZED depending on intended behavior of
attachmentService.uploadToTicket; update the method name or the assertion in
AttachmentServiceTest.uploadToTicket test accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 718f7f6b-66a7-4c50-8bf9-b1227d166a62

📥 Commits

Reviewing files that changed from the base of the PR and between 41c00e6 and aac83f8.

📒 Files selected for processing (4)
  • src/main/java/org/example/alfs/services/AttachmentService.java
  • src/test/java/org/example/alfs/services/AttachmentServiceTest.java
  • src/test/java/org/example/alfs/services/AuthServiceTest.java
  • src/test/java/org/example/alfs/services/TicketServiceTest.java
💤 Files with no reviewable changes (2)
  • src/test/java/org/example/alfs/services/TicketServiceTest.java
  • src/test/java/org/example/alfs/services/AuthServiceTest.java

Comment thread src/test/java/org/example/alfs/services/AttachmentServiceTest.java

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (3)
src/test/java/org/example/alfs/services/AttachmentServiceTest.java (3)

166-263: Access-control matrix is thorough — consider whether tests belong here or in UploadToTicketTest.

All CheckAccessTest cases exercise checkAccess indirectly through uploadToTicket, which is fine, but means failures here can be caused by unrelated changes to the upload pipeline. If checkAccess is (or can be made) package-private, calling it directly would give these tests tighter scope and avoid the need to stub storageService.upload / file.getOriginalFilename in the allowed-path cases. Not blocking — purely an optional structural cleanup.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/test/java/org/example/alfs/services/AttachmentServiceTest.java` around
lines 166 - 263, These tests exercise access control indirectly via
attachmentService.uploadToTicket which forces stubbing of storageService.upload
and MultipartFile behavior; instead, extract or expose the checkAccess logic
(the method checkAccess or equivalent inside AttachmentService) as
package-private and write the access-focused assertions to call checkAccess
directly from CheckAccessTest, so allowed-path tests no longer need to stub
storageService.upload or file.getOriginalFilename — update CheckAccessTest to
invoke AttachmentService.checkAccess(ticketId, user, reporterToken) (or the
precise method name) and keep uploadToTicket tests (UploadToTicketTest) for
end-to-end upload behavior.

139-149: Consider also verifying persistence on the filename-fallback path.

The test asserts the fallback name but doesn't verify attachmentRepository.save(...) was invoked. Adding verify(attachmentRepository).save(any(Attachment.class)); (and optionally assertThat(result.getS3Key()).isEqualTo("s3-key")) would make the happy-path expectations explicit and symmetric with the other upload tests.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/test/java/org/example/alfs/services/AttachmentServiceTest.java` around
lines 139 - 149, Update the test nullFileName_fallsBackToDefaultName in
AttachmentServiceTest to also verify persistence and S3 key: after calling
attachmentService.uploadToTicket(10L, file, admin, null) add a
verify(attachmentRepository).save(any(Attachment.class)) to ensure the
Attachment was persisted, and add an assertion that result.getS3Key()
isEqualTo("s3-key") to assert the upload path; this uses the existing mocks
(ticketRepository, storageService) and the returned result from uploadToTicket.

255-262: Duplicate of anonymousReporter_withMissingToken_throwsUnauthorized in UploadToTicketTest (lines 108–116).

This test in CheckAccessTest covers the exact same scenario (anonymous caller, token == null, expects UNAUTHORIZED) as the one in UploadToTicketTest. The 401 is raised by the pre-access token validation in uploadToTicket, not by checkAccess, so it arguably belongs only in the upload suite. Consider removing this one or reshaping it to actually exercise checkAccess (e.g., with a non-empty token that doesn't match the ticket's reporter token — though that case is already covered by anonymousReporter_withWrongToken_throwsNotFound).

✂️ Suggested removal
-        `@Test`
-        `@DisplayName`("Anonymous reporter with no token denied")
-        void anonymousReporter_withMissingToken_throwsUnauthorized() {
-            ResponseStatusException ex = assertThrows(ResponseStatusException.class,
-                    () -> attachmentService.uploadToTicket(10L, file, null, null));
-
-            assertThat(ex.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED);
-        }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/test/java/org/example/alfs/services/AttachmentServiceTest.java` around
lines 255 - 262, The test anonymousReporter_withMissingToken_throwsUnauthorized
in AttachmentServiceTest duplicates the same scenario already covered in
UploadToTicketTest (uploadToTicket with token == null), so either delete this
test from AttachmentServiceTest or convert it to directly exercise the
checkAccess method: replace the call to attachmentService.uploadToTicket(10L,
file, null, null) with a call that invokes checkAccess (e.g.,
attachmentService.checkAccess(ticketId, token)) using a non-null token that
should exercise the checkAccess logic (or assert the specific exception expected
from checkAccess), and keep the test name in sync with the new behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/test/java/org/example/alfs/services/AttachmentServiceTest.java`:
- Around line 166-263: These tests exercise access control indirectly via
attachmentService.uploadToTicket which forces stubbing of storageService.upload
and MultipartFile behavior; instead, extract or expose the checkAccess logic
(the method checkAccess or equivalent inside AttachmentService) as
package-private and write the access-focused assertions to call checkAccess
directly from CheckAccessTest, so allowed-path tests no longer need to stub
storageService.upload or file.getOriginalFilename — update CheckAccessTest to
invoke AttachmentService.checkAccess(ticketId, user, reporterToken) (or the
precise method name) and keep uploadToTicket tests (UploadToTicketTest) for
end-to-end upload behavior.
- Around line 139-149: Update the test nullFileName_fallsBackToDefaultName in
AttachmentServiceTest to also verify persistence and S3 key: after calling
attachmentService.uploadToTicket(10L, file, admin, null) add a
verify(attachmentRepository).save(any(Attachment.class)) to ensure the
Attachment was persisted, and add an assertion that result.getS3Key()
isEqualTo("s3-key") to assert the upload path; this uses the existing mocks
(ticketRepository, storageService) and the returned result from uploadToTicket.
- Around line 255-262: The test
anonymousReporter_withMissingToken_throwsUnauthorized in AttachmentServiceTest
duplicates the same scenario already covered in UploadToTicketTest
(uploadToTicket with token == null), so either delete this test from
AttachmentServiceTest or convert it to directly exercise the checkAccess method:
replace the call to attachmentService.uploadToTicket(10L, file, null, null) with
a call that invokes checkAccess (e.g., attachmentService.checkAccess(ticketId,
token)) using a non-null token that should exercise the checkAccess logic (or
assert the specific exception expected from checkAccess), and keep the test name
in sync with the new behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ae8010c2-835e-45f7-886f-b07da8ac6e74

📥 Commits

Reviewing files that changed from the base of the PR and between aac83f8 and fd4d965.

📒 Files selected for processing (2)
  • src/main/java/org/example/alfs/services/AttachmentService.java
  • src/test/java/org/example/alfs/services/AttachmentServiceTest.java
💤 Files with no reviewable changes (1)
  • src/main/java/org/example/alfs/services/AttachmentService.java

@simonforsberg
simonforsberg merged commit 66e9cca into main Apr 24, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant