Skip to content

Conversation

@aninagotgit
Copy link
Contributor

@aninagotgit aninagotgit commented Aug 6, 2025

test: add unit tests
test: move contextLoads test to IT package
refactor: convert field injection to constructor injection in JwtAuthenticationHelper

Closes #26

Summary by CodeRabbit

  • Refactor

    • Improved test class naming for clarity and consistency.
  • Style

    • Updated dependency injection style for improved maintainability.
  • Tests

    • Introduced comprehensive unit and integration tests covering analytics, books, borrowings, email, members, newsletters, notifications, authentication, and user management.
    • Added utility methods for generating test data and supporting reusable test setups.

test: move contextLoads test to IT package
refactor: convert field injection to constructor injection in JwtAuthenticationHelper
@coderabbitai
Copy link

coderabbitai bot commented Aug 6, 2025

Walkthrough

This update introduces a comprehensive suite of new unit and integration tests for the library management API, covering service, security, notification, and utility components. It also refactors the JWT authentication helper to use constructor-based dependency injection and renames an integration test class for consistency. The changes centralize test data creation and ensure robust test coverage.

Changes

Cohort / File(s) Change Summary
Test Utility Introduction
src/test/java/com/libraryman_api/TestUtil.java
Adds a new TestUtil class providing reusable static methods and constants for generating test data and DTOs, centralizing test data creation for consistency and maintainability.
Integration Test Class Rename
src/it/java/com/libraryman_api/LibrarymanApiApplicationIntegrationTest.java
Renames the integration test class from LibrarymanApiApplicationTests to LibrarymanApiApplicationIntegrationTest for naming consistency.
JWT Helper Refactor
src/main/java/com/libraryman_api/security/jwt/JwtAuthenticationHelper.java
Changes JWT secret injection from field-based to constructor-based using @Value, making the secret field final and set via the constructor.
Analytics Service Tests
src/test/java/com/libraryman_api/analytics/AnalyticsServiceTest.java
Introduces unit tests for AnalyticsService, mocking repositories and verifying methods for library overview, popular books, trends, and member activity reports.
Book Service Tests
src/test/java/com/libraryman_api/book/BookServiceTest.java
Adds comprehensive unit tests for BookService, covering CRUD operations, search, and entity/DTO mapping, including exception scenarios.
Borrowing Service Tests
src/test/java/com/libraryman_api/borrowing/BorrowingServiceTest.java
Adds detailed unit tests for BorrowingService, covering borrowing, returning, fine payment, updating book copies, and member borrowing retrieval, including positive and negative paths.
Email Service Tests
src/test/java/com/libraryman_api/email/EmailServiceTest.java
Introduces unit tests for EmailService, verifying email sending (with and without custom sender), error handling, and notification status updates.
Member Service Tests
src/test/java/com/libraryman_api/member/MemberServiceTest.java
Adds comprehensive unit tests for MemberService, covering member CRUD, password updates, and entity/DTO mapping, with extensive exception handling.
Newsletter Service Tests
src/test/java/com/libraryman_api/newsletter/NewsletterServiceTest.java
Introduces unit tests for NewsletterService, verifying subscription and unsubscription flows, including edge cases and error handling.
Notification Service Tests
src/test/java/com/libraryman_api/notification/NotificationServiceTest.java
Adds unit tests for NotificationService, covering all notification scenarios and scheduled reminders, verifying correct email and notification handling.
JWT Filter Tests
src/test/java/com/libraryman_api/security/jwt/JwtAuthenticationFilterTest.java
Introduces unit tests for JwtAuthenticationFilter, covering authentication scenarios, error handling, and security context management.
JWT Helper Tests
src/test/java/com/libraryman_api/security/jwt/JwtAuthenticationHelperTest.java
Adds unit tests for JwtAuthenticationHelper, verifying token generation and username extraction, including malformed and expired token handling.
Custom User Details Service Tests
src/test/java/com/libraryman_api/security/services/CustomUserDetailsServiceTest.java
Adds unit tests for CustomUserDetailsService, verifying user loading and exception handling for missing users.
Login Service Tests
src/test/java/com/libraryman_api/security/services/LoginServiceTest.java
Introduces unit tests for LoginService, covering successful login and error scenarios for bad credentials and user not found.
Signup Service Tests
src/test/java/com/libraryman_api/security/services/SignupServiceTest.java
Adds unit tests for SignupService, covering user, admin, and librarian signups, including duplicate user checks and field verification.

Sequence Diagram(s)

sequenceDiagram
    participant TestClass as Test Class
    participant Service as Service Under Test
    participant Repo as Mocked Repository
    participant Util as TestUtil

    TestClass->>Util: Generate test data (DTOs, entities)
    TestClass->>Repo: Setup mock return values
    TestClass->>Service: Call service method with test data
    Service->>Repo: Interact with repository (e.g., find, save)
    Repo-->>Service: Return mocked data
    Service-->>TestClass: Return result
    TestClass->>TestClass: Assert result or exception
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20–25 minutes

Poem

In the warren of code, new tests now hop,
Each service and helper gets a thorough mop.
With carrots of coverage and lettuce of mocks,
Bugs must beware—these tests truly rock!
🐇✨
Now every library bunny can rest,
For their code is robust, and their warren is blessed.

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

🎉 Thank you @aninagotgit for your contribution! Your pull request has been submitted successfully, and a maintainer will review it soon. We’re excited to have you on board! Remember to star the repo 🌟 to help us grow, and follow @ajaynegi45 to stay in the loop and increase the visibility of your contributions!


@SpringBootTest
class LibrarymanApiApplicationTests {
class LibrarymanApiApplicationIntegrationTest {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Moved the test that requires the Spring application context to start up into a folder for Integration tests. (IT)
More integration tests can be added here.


public JwtAuthenticationHelper(@Value("${jwt.secretKey}") String secret) {
this.secret = secret;
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Use constructor injection instead of field injection in order to write tests.

@aninagotgit aninagotgit marked this pull request as ready for review August 6, 2025 17:59
Copy link

@coderabbitai coderabbitai bot left a comment

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 (6)
src/test/java/com/libraryman_api/borrowing/BorrowingServiceTest.java (2)

59-59: Consider using mock returns instead of calling real methods in unit tests.

The thenCallRealMethod() calls at lines 59, 86, and in the borrowBook success test (lines 108-112) break unit test isolation by invoking actual implementation code. This can make tests brittle and harder to maintain.

Consider mocking these method calls with appropriate return values:

-when(bookService.EntityToDto(any())).thenCallRealMethod();
+when(bookService.EntityToDto(any())).thenReturn(TestUtil.getBookDto());

Also applies to: 86-86, 108-112


160-160: Consider extracting date creation logic to improve test readability.

The repeated date manipulation using LocalDate.now().plusDays/minusDays creates verbose and repetitive code that affects readability.

Consider adding helper methods to TestUtil for common date scenarios:

// In TestUtil class
public static Date getFutureDueDate() {
    return Date.from(LocalDate.now().plusDays(1).atStartOfDay(ZoneId.systemDefault()).toInstant());
}

public static Date getPastDueDate() {
    return Date.from(LocalDate.now().minusDays(1).atStartOfDay(ZoneId.systemDefault()).toInstant());
}

Also applies to: 190-190, 204-204, 220-220, 236-236, 253-253

src/test/java/com/libraryman_api/security/jwt/JwtAuthenticationHelperTest.java (2)

28-30: Consider using a more secure approach for test secrets.

The hardcoded JWT secret in the test setup could be improved for maintainability and security best practices, even in tests.

Consider using a constant or configuration approach:

+    private static final String TEST_JWT_SECRET = "aVeryLongSecretStringThatIsAtLeast64BytesLongAndSecureEnoughForHS512";
+    
     @BeforeEach
     void setup() {
-        secret = "aVeryLongSecretStringThatIsAtLeast64BytesLongAndSecureEnoughForHS512";
+        secret = TEST_JWT_SECRET;
         jwtAuthenticationHelper = new JwtAuthenticationHelper(secret);
     }

37-37: Extract magic number to improve readability.

The hardcoded expiration time (100000) should be extracted to a constant for better maintainability.

+    private static final long TOKEN_EXPIRATION_TIME = 100000;
+    
-            String token = Jwts.builder().signWith(Keys.hmacShaKeyFor(secret.getBytes()), SignatureAlgorithm.HS256).setSubject(expectedUsername).setIssuedAt(new Date()).setExpiration(new Date(System.currentTimeMillis() + 100000)).compact();
+            String token = Jwts.builder().signWith(Keys.hmacShaKeyFor(secret.getBytes()), SignatureAlgorithm.HS256).setSubject(expectedUsername).setIssuedAt(new Date()).setExpiration(new Date(System.currentTimeMillis() + TOKEN_EXPIRATION_TIME)).compact();
src/test/java/com/libraryman_api/security/services/SignupServiceTest.java (1)

32-32: Consider mocking PasswordEncoder for better test isolation.

Using a real PasswordEncoder instance creates a dependency on the actual implementation. Consider mocking it to improve test isolation and performance.

+    @Mock
+    private PasswordEncoder passwordEncoder;
-    private final PasswordEncoder passwordEncoder = new PasswordEncoder();

Then in setup method, you can stub the encoding behavior if needed:

when(passwordEncoder.encode(any())).thenReturn("encodedPassword");
src/test/java/com/libraryman_api/email/EmailServiceTest.java (1)

50-54: Consider using Spring's test utilities for property injection.

Using reflection to inject properties makes the test more fragile and harder to maintain. Consider using Spring's @TestPropertySource or ReflectionTestUtils.setField() for cleaner property injection.

+import org.springframework.test.util.ReflectionTestUtils;
+
-    private void injectPropertyValue(Object emailService) throws Exception {
-        Field field = emailService.getClass().getDeclaredField("domainName");
-        field.setAccessible(true);
-        field.set(emailService, "default.io");
-    }
+    private void injectPropertyValue(Object emailService) {
+        ReflectionTestUtils.setField(emailService, "domainName", "default.io");
+    }

And update the setup method to remove the Exception handling:

-    void setup() throws Exception {
+    void setup() {
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 20d628e and 6b2824d.

📒 Files selected for processing (15)
  • src/it/java/com/libraryman_api/LibrarymanApiApplicationIntegrationTest.java (1 hunks)
  • src/main/java/com/libraryman_api/security/jwt/JwtAuthenticationHelper.java (1 hunks)
  • src/test/java/com/libraryman_api/TestUtil.java (1 hunks)
  • src/test/java/com/libraryman_api/analytics/AnalyticsServiceTest.java (1 hunks)
  • src/test/java/com/libraryman_api/book/BookServiceTest.java (1 hunks)
  • src/test/java/com/libraryman_api/borrowing/BorrowingServiceTest.java (1 hunks)
  • src/test/java/com/libraryman_api/email/EmailServiceTest.java (1 hunks)
  • src/test/java/com/libraryman_api/member/MemberServiceTest.java (1 hunks)
  • src/test/java/com/libraryman_api/newsletter/NewsletterServiceTest.java (1 hunks)
  • src/test/java/com/libraryman_api/notification/NotificationServiceTest.java (1 hunks)
  • src/test/java/com/libraryman_api/security/jwt/JwtAuthenticationFilterTest.java (1 hunks)
  • src/test/java/com/libraryman_api/security/jwt/JwtAuthenticationHelperTest.java (1 hunks)
  • src/test/java/com/libraryman_api/security/services/CustomUserDetailsServiceTest.java (1 hunks)
  • src/test/java/com/libraryman_api/security/services/LoginServiceTest.java (1 hunks)
  • src/test/java/com/libraryman_api/security/services/SignupServiceTest.java (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
src/test/java/com/libraryman_api/security/services/SignupServiceTest.java (3)
src/test/java/com/libraryman_api/TestUtil.java (1)
  • TestUtil (23-158)
src/main/java/com/libraryman_api/exception/ResourceNotFoundException.java (1)
  • ResourceNotFoundException (11-51)
src/test/java/com/libraryman_api/security/services/CustomUserDetailsServiceTest.java (1)
  • ExtendWith (25-51)
src/test/java/com/libraryman_api/book/BookServiceTest.java (3)
src/test/java/com/libraryman_api/TestUtil.java (2)
  • TestUtil (23-158)
  • Constant (152-157)
src/main/java/com/libraryman_api/exception/InvalidSortFieldException.java (1)
  • InvalidSortFieldException (11-51)
src/main/java/com/libraryman_api/exception/ResourceNotFoundException.java (1)
  • ResourceNotFoundException (11-51)
🔇 Additional comments (35)
src/main/java/com/libraryman_api/security/jwt/JwtAuthenticationHelper.java (1)

19-23: LGTM! Constructor injection implemented as requested.

This refactoring successfully addresses the past review comment by converting from field injection to constructor injection. The final keyword ensures immutability and the constructor parameter approach enables easier unit testing and follows Spring best practices.

src/test/java/com/libraryman_api/TestUtil.java (4)

26-28: LGTM! Simple and effective random number generation for tests.

The fixed range (100-1000) provides predictable test data while avoiding collisions with the hardcoded constants.


30-150: Excellent test utility design for centralized test data creation.

The factory methods provide consistent, reusable test data with good separation between entities and DTOs. Using constants and providing methods for all major domain objects will significantly improve test maintainability across the project.


104-109: LGTM! Date adjustment utility is consistent with codebase.

The method correctly uses the Calendar API to adjust dates. While modern projects might prefer LocalDate, this approach is consistent with the Date usage throughout the domain entities.


111-158: Well-designed pagination utilities and constants.

The pagination helper methods and centralized constants follow excellent test utility patterns. The getPageRequest method provides consistent pagination parameters, and the constants ensure maintainable test data references across all tests.

src/it/java/com/libraryman_api/LibrarymanApiApplicationIntegrationTest.java (1)

7-7: Excellent organizational improvement for integration tests.

Renaming the class to LibrarymanApiApplicationIntegrationTest and moving it to the IT package clearly separates integration tests from unit tests and makes the test purpose explicit. This follows best practices for test organization.

src/test/java/com/libraryman_api/analytics/AnalyticsServiceTest.java (4)

34-45: LGTM! Well-structured test for library overview aggregation.

The test properly mocks all repository count methods and verifies the service correctly aggregates the data into the expected map structure.


47-55: LGTM! Appropriate test for popular books retrieval.

The test correctly verifies that the service properly delegates to the repository and returns the expected popular books data.


57-65: LGTM! Good use of flexible matchers for date-based queries.

The test appropriately uses any() matchers for the date parameters, focusing on verifying the service correctly returns trending data rather than getting bogged down in specific date values.


67-75: LGTM! Straightforward test for member activity reporting.

The test correctly verifies that the service properly retrieves and returns member activity report data from the repository.

src/test/java/com/libraryman_api/book/BookServiceTest.java (8)

34-56: Excellent test coverage for getAllBooks functionality.

The nested class properly tests both successful book retrieval with pagination and exception handling for invalid sort fields. The exception translation from PropertyReferenceException to InvalidSortFieldException is correctly verified.


58-79: LGTM! Proper testing of Optional return pattern.

The tests correctly verify both successful book retrieval and empty results, properly using the Optional pattern and realistic test scenarios with random IDs for non-existent records.


81-89: LGTM! Clean test for book addition functionality.

The test properly verifies the add book functionality with appropriate mocking and DTO conversion validation.


91-119: Comprehensive testing of book update scenarios.

The nested class properly tests both successful updates and exception handling. The success test correctly verifies that existing book data is retrieved, updated with new values, and saved, while the exception test confirms proper error handling for non-existent books.


121-139: LGTM! Appropriate testing of deletion scenarios.

The tests correctly verify successful deletion using assertDoesNotThrow and proper exception handling with meaningful error messages for non-existent books.


141-155: Thorough verification of entity to DTO conversion.

The test comprehensively verifies that all fields are correctly mapped from the Book entity to BookDto, ensuring data integrity during conversion.


157-171: Comprehensive verification of DTO to entity conversion.

The test thoroughly verifies that all fields are correctly mapped from BookDto to Book entity, ensuring proper bidirectional conversion functionality.


173-181: LGTM! Effective test for book search functionality.

The test properly verifies the search functionality by mocking the repository search method and confirming the service returns the expected paginated results.

src/test/java/com/libraryman_api/borrowing/BorrowingServiceTest.java (1)

1-429: Excellent test coverage and organization!

The test class demonstrates comprehensive coverage of the BorrowingService with well-structured nested classes, good separation of concerns, and thorough testing of both success and failure scenarios. The use of descriptive test method names and proper exception message assertions enhances maintainability.

src/test/java/com/libraryman_api/member/MemberServiceTest.java (3)

40-45: Good practice using real PasswordEncoder for testing password functionality.

Using a real PasswordEncoder instance instead of mocking it ensures that password encoding/decoding logic is properly tested, which is critical for security functionality.


156-206: Comprehensive password update testing with excellent scenario coverage.

The password update tests cover all critical scenarios: success, member not found, incorrect current password, and same password validation. The test setup properly encodes passwords and validates the behavior correctly.


208-236: Thorough testing of DTO-Entity conversion methods.

The conversion method tests verify all field mappings between DTOs and entities, ensuring data integrity during transformations.

src/test/java/com/libraryman_api/security/services/CustomUserDetailsServiceTest.java (1)

35-42: Clean and focused test implementation.

The test correctly verifies that the service returns the expected Members object as UserDetails and properly handles the not-found scenario with appropriate exception throwing.

src/test/java/com/libraryman_api/security/services/LoginServiceTest.java (1)

44-69: Comprehensive login service testing with proper exception handling.

The test suite effectively covers the main authentication scenarios: successful login with token generation, bad credentials handling, and user not found cases. The exception propagation testing ensures proper error handling behavior.

src/test/java/com/libraryman_api/security/jwt/JwtAuthenticationFilterTest.java (3)

39-42: Excellent test setup with proper SecurityContext management.

Clearing the SecurityContext in @BeforeEach ensures test isolation and prevents test interference, which is crucial for security-related testing.


79-90: Sophisticated parameterized testing for JWT exceptions.

The use of @ParameterizedTest with dynamic class loading to test different JWT exception types is an elegant solution that reduces code duplication while ensuring comprehensive exception handling coverage.


46-144: Exceptionally comprehensive JWT filter testing.

This test suite covers all critical authentication scenarios including valid tokens, missing/invalid headers, various JWT exceptions, expired tokens, and pre-existing security contexts. The thorough coverage ensures robust JWT authentication behavior.

src/test/java/com/libraryman_api/security/jwt/JwtAuthenticationHelperTest.java (1)

66-76: Excellent comprehensive test coverage!

The test thoroughly validates token generation by verifying claims extraction, subject matching, and presence of issued/expiration dates. The use of TestUtil for consistent test data is also well implemented.

src/test/java/com/libraryman_api/security/services/SignupServiceTest.java (1)

43-84: Excellent test structure and coverage!

The nested class organization and comprehensive testing of both success and failure scenarios is well implemented. The use of ArgumentCaptor to verify saved entity properties and the thorough exception testing demonstrate good testing practices.

src/test/java/com/libraryman_api/notification/NotificationServiceTest.java (3)

168-174: Excellent helper method design!

The verifyEmailSent helper method effectively reduces code duplication and provides consistent verification across all notification tests. The parameter design allows for flexible verification of email components.


131-166: Comprehensive edge case testing in SendDueDateReminders.

The nested class provides excellent coverage of the scheduled reminder functionality, including success scenarios, empty results, and missing member handling. This demonstrates thorough testing of the automated reminder system.


70-70: TestUtil provides all referenced methods – no action required

TestUtil defines the needed static helpers:

  • src/test/java/com/libraryman_api/TestUtil.java
    • getFine() at line 67
    • getBorrowings() at line 94
src/test/java/com/libraryman_api/email/EmailServiceTest.java (1)

90-110: Excellent notification status testing!

The Send nested class effectively tests both successful email sending (status set to SENT) and failure scenarios (status set to FAILED). This ensures proper notification tracking and error handling.

src/test/java/com/libraryman_api/newsletter/NewsletterServiceTest.java (2)

31-80: Comprehensive subscription testing with good edge case coverage.

The Subscribe nested class thoroughly tests all subscription scenarios: re-subscription of inactive users, handling already active subscriptions, new subscriber creation, and email validation. The verification of repository and email service interactions is well implemented.


82-122: Well-structured unsubscription testing.

The Unsubscribe nested class effectively covers all unsubscription scenarios including successful unsubscription, invalid tokens, and already unsubscribed users. The test organization and verification patterns are consistent and maintainable.

Comment on lines +69 to +72
Exception exception = assertThrows(ResourceNotFoundException.class, () -> signupService.signup(members));

assertEquals("User already Exists", exception.getMessage());
}
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Verify exception type usage - ResourceNotFoundException for user existence checks.

The tests throw ResourceNotFoundException with message "User already Exists" for duplicate users. This seems semantically incorrect - typically ResourceNotFoundException indicates a resource wasn't found, not that it already exists. Consider if a different exception type would be more appropriate.

Let me verify how the actual SignupService handles these cases:

Also applies to: 80-83, 112-115, 123-126, 155-158, 166-169


🏁 Script executed:

#!/bin/bash
# Description: Check how SignupService handles duplicate user scenarios
# Expected: Should show the actual exception types used

ast-grep --pattern $'class SignupService {
  $$$
  signup($_) {
    $$$
  }
  $$$
}'

Length of output: 85


🏁 Script executed:

#!/bin/bash
# Locate the file defining SignupService
rg -l "class\s\+SignupService" -n .

# For each matched file, show the signup method and any exception throws
for file in $(rg -l "class\s\+SignupService" -n .); do
  echo "==== Inspecting $file ===="
  rg -n "signup" "$file" -C 5
  echo
  rg -n "throw new" "$file" -C 3
done

Length of output: 76


🏁 Script executed:

#!/bin/bash
# Search for SignupService implementation files anywhere in the repo
echo "Locating SignupService Java files..."
find . -type f -iname "*signupservice*.java" -print

# For each located file, extract the signup method and any thrown exceptions
for file in $(find . -type f -iname "*signupservice*.java"); do
  echo
  echo "==== Inspecting $file ===="
  echo "-- Method signature and body around signup --"
  grep -n "signup(" "$file" -C5 || echo "  → No signup() signature found here"
  echo
  echo "-- Exception throws in this class --"
  grep -n "throw new" "$file" -C3 || echo "  → No throw statements found here"
done

Length of output: 5741


Use a semantically accurate exception for duplicate users

The signup method currently throws ResourceNotFoundException("User already Exists") when a user already exists—this is misleading, since “not found” implies absence, not presence. Please update both the service and its tests to use an exception that clearly conveys a duplicate‐resource error (for example, DuplicateResourceException, ResourceAlreadyExistsException, or a custom UserAlreadyExistsException).

• In src/main/java/com/libraryman_api/security/services/SignupService.java, replace both

throw new ResourceNotFoundException("User already Exists");

with something like

throw new UserAlreadyExistsException("User already exists");

• In src/test/java/com/libraryman_api/security/services/SignupServiceTest.java, update the assertThrows calls at lines 69–72 and 80–83 to expect the new exception type instead of ResourceNotFoundException.

Example diff snippet:

--- a/src/main/java/com/libraryman_api/security/services/SignupService.java
+++ b/src/main/java/com/libraryman_api/security/services/SignupService.java
@@ -29,7 +29,7 @@ public void signup(Members members) {
         if (memberOptId.isPresent()) {
-            throw new ResourceNotFoundException("User already Exists");
+            throw new UserAlreadyExistsException("User already exists");
         }
         if (memberOptUsername.isPresent()) {
-            throw new ResourceNotFoundException("User already Exists");
+            throw new UserAlreadyExistsException("User already exists");
         }
--- a/src/test/java/com/libraryman_api/security/services/SignupServiceTest.java
+++ b/src/test/java/com/libraryman_api/security/services/SignupServiceTest.java
@@ -69,7 +69,7 @@ void idFound() {
-    Exception exception = assertThrows(ResourceNotFoundException.class, () -> signupService.signup(members));
+    Exception exception = assertThrows(UserAlreadyExistsException.class, () -> signupService.signup(members));
     assertEquals("User already Exists", exception.getMessage());
 }
@@ -80,7 +80,7 @@ void usernameFound() {
-    Exception exception = assertThrows(ResourceNotFoundException.class, () -> signupService.signup(members));
+    Exception exception = assertThrows(UserAlreadyExistsException.class, () -> signupService.signup(members));
     assertEquals("User already Exists", exception.getMessage());
 }
🤖 Prompt for AI Agents
In src/test/java/com/libraryman_api/security/services/SignupServiceTest.java
around lines 69 to 72, update the test to expect the new exception type
UserAlreadyExistsException instead of ResourceNotFoundException for duplicate
user signup attempts. Also, ensure the corresponding service file
src/main/java/com/libraryman_api/security/services/SignupService.java replaces
the throw of ResourceNotFoundException with UserAlreadyExistsException to
accurately reflect the error condition.

@aninagotgit aninagotgit mentioned this pull request Aug 6, 2025
Copy link
Owner

@ajaynegi45 ajaynegi45 left a comment

Choose a reason for hiding this comment

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

Hey @aninagotgit 👋

Wow — what an incredible contribution! 🚀 A 2000+ line commit that not only brings in comprehensive unit and integration tests, but also modernizes our codebase. You've clearly put a lot of thought and care into improving both the test structure and overall maintainability. 🙌

It would be awesome if you could take a look at other present issues and push a fix when you get a chance. Let me know if you need help — happy to assist!

Also, if you're enjoying working on this repo, I’d love for you to explore some of the other Java projects I maintain — especially Vayu 🌬️. It’s an evolving project with tons of interesting problems — could definitely use your eye for clean code and thoughtful testing!

Thanks again for this beast of a contribution. Can't wait to get this merged once those last bits are resolved. Keep rocking! 💪

@ajaynegi45 ajaynegi45 merged commit 8133b12 into ajaynegi45:main Aug 7, 2025
3 of 6 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.

Write Unit Tests

2 participants