Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: Improved test coverage in #31

Closed

Conversation

brettchaldecott
Copy link
Contributor

Explain your changes

Working on improving test coverage

Checklist

🛟 If you need help, consider asking for advice over in the Kinde community.

Copy link
Contributor

coderabbitai bot commented Oct 8, 2024

Walkthrough

The pull request modifies the initClient method in the KindeAdminSessionImpl class to incorporate an authMap for OAuth authentication when kindeClient is null. It also introduces a new test class, KindeAdminSessionImplTest, which contains a unit test for verifying the functionality of the initClient method. Additionally, a new JwtGenerator class is created to handle the generation of JSON Web Tokens (JWTs) with specific claims.

Changes

File Change Summary
kinde-management/src/main/java/com/kinde/admin/KindeAdminSessionImpl.java Modified initClient method logic to use an authMap for OAuth authentication when kindeClient is null.
kinde-management/src/test/java/com/kinde/admin/KindeAdminSessionImplTest.java Added unit test class KindeAdminSessionImplTest with method testInitClient to validate initClient functionality.
kinde-management/src/test/java/com/kinde/token/jwt/JwtGenerator.java Introduced JwtGenerator class with methods to generate access tokens, ID tokens, and refresh tokens using JWT.
kinde-springboot/kinde-springboot-core/src/test/java/com/kinde/spring/config/KindeOAuth2PropertiesTest.java Added test class KindeOAuth2PropertiesTest to validate properties of KindeOAuth2Properties.

Possibly related PRs

  • Feature/sdk rework #21: The changes in KindeAdminSessionImpl regarding the initClient method's authentication logic may relate to the overall SDK rework, which likely includes updates to authentication mechanisms.
  • Fix/cleanup #29: The modifications in KindeAdminSessionImpl to enhance the initClient method's logic for OAuth authentication align with the focus of this PR on upgrading library dependencies and ensuring compatibility with new versions of Spring Boot.

Suggested reviewers

  • DaveOrDead
  • rairaman

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ 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.
    • Generate unit testing code for this file.
    • 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 generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • 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 generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

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

codecov bot commented Oct 8, 2024

Codecov Report

Attention: Patch coverage is 0% with 3 lines in your changes missing coverage. Please review.

Project coverage is 36.47%. Comparing base (0fa14ae) to head (a8852d6).

Files with missing lines Patch % Lines
...in/java/com/kinde/admin/KindeAdminSessionImpl.java 0.00% 3 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff              @@
##               main      #31      +/-   ##
============================================
- Coverage     42.53%   36.47%   -6.06%     
============================================
  Files            53       67      +14     
  Lines           964     1124     +160     
  Branches         76       90      +14     
============================================
  Hits            410      410              
- Misses          517      677     +160     
  Partials         37       37              
Files with missing lines Coverage Δ
...in/java/com/kinde/admin/KindeAdminSessionImpl.java 15.00% <0.00%> (-1.67%) ⬇️

... and 14 files with indirect coverage changes

Copy link
Contributor

@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: 6

🧹 Outside diff range and nitpick comments (4)
kinde-management/src/main/java/com/kinde/admin/KindeAdminSessionImpl.java (2)

Line range hint 1-52: Document new behavior and consider design improvements

The changes introduce a new behavior when kindeClient is null, but this is not documented or explained in the class. This could lead to unexpected behavior for users of this class. Consider the following improvements:

  1. Add documentation to the class and the initClient() method explaining the behavior when kindeClient is null.

  2. Reconsider the class design to handle a null kindeClient more explicitly. For example:

    a. Make kindeClient non-nullable in the constructor and provide a separate factory method for creating an instance with default authentication:

    public class KindeAdminSessionImpl implements KindeAdminSession {
        private final KindeClient kindeClient;
    
        public KindeAdminSessionImpl(KindeClient kindeClient) {
            this.kindeClient = Objects.requireNonNull(kindeClient, "kindeClient must not be null");
        }
    
        public static KindeAdminSessionImpl createWithDefaultAuth(Config config) {
            // Create and return an instance with default authentication
        }
    
        // ...
    }

    b. Or, if null kindeClient is a valid use case, make it explicit in the constructor and document it:

    public class KindeAdminSessionImpl implements KindeAdminSession {
        private final KindeClient kindeClient;
        private final Config config;
    
        /**
         * @param kindeClient The KindeClient to use, or null to use default authentication
         * @param config The configuration to use for default authentication when kindeClient is null
         */
        public KindeAdminSessionImpl(KindeClient kindeClient, Config config) {
            this.kindeClient = kindeClient;
            this.config = Objects.requireNonNull(config, "config must not be null");
        }
    
        // ...
    }

These changes would make the class's behavior more explicit and easier to understand for developers using this class.


Line range hint 1-52: Minor improvements for code quality and robustness

Here are a few minor suggestions to improve the overall quality and robustness of the code:

  1. Consider using constructor injection consistently. Instead of setting kindeClient in the constructor and creating other dependencies in the initClient() method, you could inject all necessary dependencies:
public class KindeAdminSessionImpl implements KindeAdminSession {
    private final KindeClient kindeClient;
    private final Config config;

    public KindeAdminSessionImpl(KindeClient kindeClient, Config config) {
        this.kindeClient = kindeClient;
        this.config = Objects.requireNonNull(config, "config must not be null");
    }

    // ...
}
  1. Add a null check for kindeTokens.getAccessToken() to make the code more robust:
KindeTokens kindeTokens = kindeClient.clientSession().retrieveTokens();
if (kindeTokens == null || kindeTokens.getAccessToken() == null) {
    throw new IllegalStateException("Invalid session type or missing access token.");
}
AccessToken accessToken = kindeTokens.getAccessToken();
  1. Consider using final for variables that are not reassigned to make the code's intent clearer:
final Map<String, Authentication> authMap = new HashMap<>();
final ApiClient apiClient = new ApiClient(authMap);

These changes would further improve the code quality and make it more robust against potential null pointer exceptions.

kinde-management/src/test/java/com/kinde/admin/KindeAdminSessionImplTest.java (2)

26-30: Add assertion for ApiClient result.

The test creates a KindeAdminSessionImpl instance with a null parameter and calls initClient(), but it doesn't verify the result. Consider adding an assertion to ensure that the returned ApiClient is not null or has expected properties.

Example assertion:

assertNotNull(apiClient, "ApiClient should not be null");

31-46: LGTM: Comprehensive mocking setup with a minor suggestion.

The mocking setup is thorough and covers all necessary dependencies for the test. The use of JwtGenerator for creating mock tokens is a good practice.

To improve readability, consider extracting the mock setup into a separate method, e.g., setupMocks(). This would make the test method more concise and easier to understand.

Example refactoring:

private void setupMocks(KindeClient kindeClient) throws Exception {
    KindeClientSession kindeClientSession = Mockito.mock(KindeClientSession.class);
    when(kindeClient.clientSession()).thenReturn(kindeClientSession);
    // ... (rest of the mock setup)
}

@Test
public void testInitClient() throws Exception {
    // ... (first part of the test)
    KindeClient kindeClient = Mockito.mock(KindeClient.class);
    setupMocks(kindeClient);
    // ... (rest of the test)
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 0fa14ae and 362c75e.

⛔ Files ignored due to path filters (1)
  • kinde-management/pom.xml is excluded by !**/*.xml
📒 Files selected for processing (3)
  • kinde-management/src/main/java/com/kinde/admin/KindeAdminSessionImpl.java (1 hunks)
  • kinde-management/src/test/java/com/kinde/admin/KindeAdminSessionImplTest.java (1 hunks)
  • kinde-management/src/test/java/com/kinde/token/jwt/JwtGenerator.java (1 hunks)
🧰 Additional context used
📓 Learnings (1)
kinde-management/src/test/java/com/kinde/token/jwt/JwtGenerator.java (2)
Learnt from: brettchaldecott
PR: kinde-oss/kinde-java-sdk#21
File: kinde-core/src/test/java/com/kinde/token/jwt/JwtGenerator.java:82-110
Timestamp: 2024-08-19T09:42:12.291Z
Learning: Hardcoded claims and key IDs in the `refreshToken` method are acceptable for testing purposes.
Learnt from: brettchaldecott
PR: kinde-oss/kinde-java-sdk#21
File: kinde-core/src/test/java/com/kinde/token/jwt/JwtGenerator.java:19-48
Timestamp: 2024-08-19T09:41:56.859Z
Learning: The `generateAccessToken` method in `JwtGenerator` is used for testing purposes, and hardcoded values are acceptable in this context.
🔇 Additional comments (2)
kinde-management/src/test/java/com/kinde/admin/KindeAdminSessionImplTest.java (1)

1-23: LGTM: Import statements are appropriate and concise.

The import statements cover all necessary classes for the test implementation, including Kinde SDK components, Nimbus JOSE + JWT library for OIDC-related classes, and testing frameworks (JUnit and Mockito).

kinde-management/src/test/java/com/kinde/token/jwt/JwtGenerator.java (1)

1-117: Overall implementation is appropriate for testing purposes

The JwtGenerator class effectively generates JWT tokens needed for testing, and hardcoded values are acceptable in this context, as per the retrieved learnings. The use of @SneakyThrows simplifies exception handling in test code, which is also acceptable.

I utilized the context from the retrieved learnings to confirm that hardcoded values are permissible in this testing scenario.

Comment on lines +28 to +31
Map<String, Authentication> authMap = new HashMap<>();
authMap.put("ManagementAPI",new OAuth(
"https://kinde.com","http://kinde.com/oauth2/token"));
return new ApiClient(authMap);
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Codebase verification

⚠️ Potential issue

Hardcoded URLs Identified in Multiple Locations

The review has uncovered that hardcoded URLs "https://kinde.com" and "http://kinde.com/oauth2/token" are present in several Java files, including both main and test directories. This widespread use of hardcoded authentication endpoints poses the following concerns:

  1. Maintainability: Updating the URLs requires changes in multiple files, increasing the risk of inconsistencies and errors.
  2. Flexibility: Different environments (development, staging, production) may require different URLs, which is not feasible with hardcoded values.
  3. Security: Hardcoded URLs can be a vector for security vulnerabilities if they need to be updated or if unauthorized changes occur.

Recommendations:

  • Centralize Configuration: Refactor the code to use configuration files or environment variables for authentication URLs.

    String domain = config.getKindeDomain();
    String tokenEndpoint = config.getKindeTokenEndpoint();
    authMap.put("ManagementAPI", new OAuth(domain, tokenEndpoint));
  • Implement Validation and Error Handling: Ensure that configurations are loaded correctly and handle scenarios where configurations might be missing or incorrect.

    if (kindeClient == null) {
        logger.warn("KindeClient is null. Using default authentication.");
        try {
            Map<String, Authentication> authMap = new HashMap<>();
            authMap.put("ManagementAPI", new OAuth(domain, tokenEndpoint));
            return new ApiClient(authMap);
        } catch (Exception e) {
            logger.error("Failed to initialize default ApiClient", e);
            throw new IllegalStateException("Unable to initialize ApiClient", e);
        }
    }
  • Review All Instances: Conduct a comprehensive review of all occurrences of these hardcoded URLs and apply the refactoring consistently across the codebase.

🔗 Analysis chain

Avoid using hardcoded URLs and improve error handling

While the addition of a default authentication mechanism when kindeClient is null is a good idea, there are several concerns with the current implementation:

  1. Hardcoded URLs: The URLs "https://kinde.com" and "http://kinde.com/oauth2/token" are hardcoded. This reduces flexibility and may cause issues if these URLs change or differ across environments.

  2. Lack of error handling: There's no error handling or logging for this new code path, which could make debugging difficult if issues arise.

  3. Security implications: Using hardcoded authentication endpoints could pose a security risk if these URLs change or if different environments require different URLs.

  4. Maintainability: Hardcoded values reduce maintainability and make it harder to update the code for different environments or configurations.

To address these concerns, consider the following improvements:

  1. Use configuration values instead of hardcoded URLs:
String domain = config.getKindeDomain();
String tokenEndpoint = config.getKindeTokenEndpoint();
authMap.put("ManagementAPI", new OAuth(domain, tokenEndpoint));
  1. Add error handling and logging:
if (kindeClient == null) {
    logger.warn("KindeClient is null. Using default authentication.");
    try {
        Map<String, Authentication> authMap = new HashMap<>();
        authMap.put("ManagementAPI", new OAuth(domain, tokenEndpoint));
        return new ApiClient(authMap);
    } catch (Exception e) {
        logger.error("Failed to initialize default ApiClient", e);
        throw new IllegalStateException("Unable to initialize ApiClient", e);
    }
}
  1. Consider adding a comment explaining why this default authentication is necessary when kindeClient is null.

To ensure these URLs are not used elsewhere in the codebase, you can run the following command:

This will help identify if these hardcoded URLs are used in other parts of the codebase, which might also need to be updated.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

rg --type java "https://kinde.com" "http://kinde.com/oauth2/token"

Length of output: 134


Script:

#!/bin/bash
# Corrected command to search for hardcoded URLs in Java files
rg --type java -e "https://kinde.com" -e "http://kinde.com/oauth2/token"

Length of output: 3628

Comment on lines +24 to +50
public class KindeAdminSessionImplTest {

@Test
public void testInitClient() throws Exception {
KindeAdminSessionImpl kindeAdminSession1 = new KindeAdminSessionImpl(null);
ApiClient apiClient = kindeAdminSession1.initClient();

KindeClient kindeClient = Mockito.mock(KindeClient.class);
KindeClientSession kindeClientSession = Mockito.mock(KindeClientSession.class);
when(kindeClient.clientSession()).thenReturn(kindeClientSession);
KindeConfig kindeConfig = Mockito.mock(KindeConfig.class);
when(kindeClient.kindeConfig()).thenReturn(kindeConfig);
OidcMetaData oidcMetaData = Mockito.mock(OidcMetaData.class);
when(kindeClient.oidcMetaData()).thenReturn(oidcMetaData);
OIDCProviderMetadata oidcProviderMetadata = new OIDCProviderMetadata(new Issuer("https://kinde.com"),
Arrays.asList(SubjectType.PUBLIC), new URI("https://kinde.com"));
oidcProviderMetadata.setTokenEndpointURI(new URI("https://kinde.com"));
when(oidcMetaData.getOpMetadata()).thenReturn(oidcProviderMetadata);
IDToken idToken = IDToken.init(JwtGenerator.generateIDToken(),true);
AccessToken accessToken = AccessToken.init(JwtGenerator.generateAccessToken(),true);
RefreshToken refreshToken = RefreshToken.init(JwtGenerator.refreshToken(),true);
KindeTokens kindeTokens = new KindeTokens(Arrays.asList(),idToken,accessToken,refreshToken);
when(kindeClientSession.retrieveTokens()).thenReturn(kindeTokens);
KindeAdminSessionImpl kindeAdminSession2 = new KindeAdminSessionImpl(kindeClient);
kindeAdminSession2.initClient();
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Good start, but expand test coverage and add assertions.

The test class provides a good foundation for testing the KindeAdminSessionImpl.initClient() method. However, to improve the overall test coverage and reliability, consider the following suggestions:

  1. Add assertions to verify the expected behavior in both scenarios (null and mocked KindeClient).
  2. Include error scenarios and edge cases, such as:
    • KindeClient throwing exceptions
    • Invalid or expired tokens
    • Network errors during client initialization
  3. Test different configuration scenarios (e.g., different OIDC provider metadata).
  4. Consider using parameterized tests for testing multiple scenarios efficiently.

Example additional test case:

@Test
public void testInitClientWithException() {
    KindeClient mockClient = Mockito.mock(KindeClient.class);
    when(mockClient.clientSession()).thenThrow(new RuntimeException("Session error"));

    KindeAdminSessionImpl kindeAdminSession = new KindeAdminSessionImpl(mockClient);
    
    assertThrows(RuntimeException.class, () -> kindeAdminSession.initClient(),
                 "initClient should throw RuntimeException when client session fails");
}

Comment on lines +47 to +49
KindeAdminSessionImpl kindeAdminSession2 = new KindeAdminSessionImpl(kindeClient);
kindeAdminSession2.initClient();
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Enhance test assertions and scenario verification.

The test creates two KindeAdminSessionImpl instances (one with null and one with a mocked KindeClient) but doesn't verify the behavior difference or assert the results. Consider the following improvements:

  1. Add assertions to verify the behavior of initClient() with the mocked KindeClient.
  2. Compare the results of both initClient() calls to ensure they behave differently as expected.
  3. Verify that the mocked methods were called as expected.

Example improvements:

ApiClient apiClient1 = kindeAdminSession1.initClient();
assertNotNull(apiClient1, "ApiClient should not be null for null KindeClient");

KindeAdminSessionImpl kindeAdminSession2 = new KindeAdminSessionImpl(kindeClient);
ApiClient apiClient2 = kindeAdminSession2.initClient();
assertNotNull(apiClient2, "ApiClient should not be null for mocked KindeClient");

// Verify that the mocked methods were called
Mockito.verify(kindeClient).clientSession();
Mockito.verify(kindeClient).kindeConfig();
Mockito.verify(kindeClient).oidcMetaData();
Mockito.verify(kindeClientSession).retrieveTokens();

// Compare the two ApiClient instances if they should be different
assertNotEquals(apiClient1, apiClient2, "ApiClient instances should be different for null and mocked KindeClient");

RSAKey rsaJWK = new RSAKeyGenerator(2048)
.keyID("123")
.generate();
RSAKey rsaPublicJWK = rsaJWK.toPublicJWK();
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Remove unused variable rsaPublicJWK

The variable rsaPublicJWK declared in methods generateAccessToken (line 23), generateIDToken (line 54), and refreshToken (line 93) is never used in the code. Removing this unused variable will clean up the code and eliminate any potential confusion.

Apply this diff to remove the unused variable:

-            RSAKey rsaPublicJWK = rsaJWK.toPublicJWK();

Also applies to: 54-54, 93-93

Comment on lines +17 to +46
public static String generateAccessToken() {

// generate a new signed token
RSAKey rsaJWK = new RSAKeyGenerator(2048)
.keyID("123")
.generate();
RSAKey rsaPublicJWK = rsaJWK.toPublicJWK();

JWSSigner signer = new RSASSASigner(rsaJWK);

Date now = new Date();

JWTClaimsSet jwtClaims = new JWTClaimsSet.Builder()
.issuer("https://openid.net")
.subject("test")
.audience(Arrays.asList("https://kinde.com"))
.expirationTime(new Date(now.getTime() + 1000*60*10)) // expires in 10 minutes
.notBeforeTime(now)
.issueTime(now)
.claim("permissions",Arrays.asList("test1","test1"))
.jwtID(UUID.randomUUID().toString())
.build();

SignedJWT signedJWT = new SignedJWT(
new JWSHeader.Builder(JWSAlgorithm.RS256).keyID(rsaJWK.getKeyID()).build(),
jwtClaims);

signedJWT.sign(signer);
return signedJWT.serialize();
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Refactor common code to reduce duplication

The methods generateAccessToken, generateIDToken, and refreshToken share significant portions of code, such as RSA key generation, signer initialization, and claim setup. Consider refactoring the common code into private helper methods or a constructor to enhance maintainability and reduce duplication.

For example, you can create a private method to generate the RSA key and signer:

@SneakyThrows
private static RSASSASigner getSigner() {
    RSAKey rsaJWK = new RSAKeyGenerator(2048)
            .keyID("123")
            .generate();
    return new RSASSASigner(rsaJWK);
}

And another private method to build the common JWT claims:

private static JWTClaimsSet.Builder getCommonClaims(Date now) {
    return new JWTClaimsSet.Builder()
            .issuer("https://openid.net")
            .subject("test")
            .audience(Collections.singletonList("https://kinde.com"))
            .expirationTime(new Date(now.getTime() + 1000 * 60 * 10)) // expires in 10 minutes
            .notBeforeTime(now)
            .issueTime(now)
            .claim("permissions", Arrays.asList("test1", "test1"))
            .jwtID(UUID.randomUUID().toString());
}

This refactoring will make your test code cleaner and more manageable.

Also applies to: 49-85, 88-116

Comment on lines +20 to +22
RSAKey rsaJWK = new RSAKeyGenerator(2048)
.keyID("123")
.generate();
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Reuse RSA key instead of generating a new one in each method

Currently, each method generates a new RSA key pair every time it's called. This can be inefficient and unnecessary for testing purposes. Consider generating the RSA key once and reusing it across all methods to improve efficiency.

For example, you can declare the RSA key as a static variable:

private static final RSAKey RSA_JWK = new RSAKeyGenerator(2048)
        .keyID("123")
        .generate();

private static final JWSSigner SIGNER = new RSASSASigner(RSA_JWK);

Then, use SIGNER in your methods without generating new keys each time.

Also applies to: 51-53, 90-92

Copy link
Contributor

@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

🧹 Outside diff range and nitpick comments (3)
kinde-springboot/kinde-springboot-core/src/test/java/com/kinde/spring/config/KindeOAuth2PropertiesTest.java (3)

8-13: LGTM: Test class and method setup are well-structured.

The class and method names follow proper conventions, and the use of Mockito for OAuth2ClientProperties is appropriate for unit testing.

Consider adding a brief JavaDoc comment for the test method to describe its purpose and what aspects of KindeOAuth2Properties it's testing. This would improve the test's documentation and make it easier for other developers to understand the test's intent.


15-25: LGTM: Comprehensive checks for default values.

The test thoroughly verifies the initial state of KindeOAuth2Properties, including null checks for most properties and specific checks for audience and permissionsClaim.

Consider grouping related assertions together and adding comments to separate different groups of checks. This would improve the readability of the test. For example:

// Check that most properties are initially null
Assert.assertNull(kindeOAuth2Properties.getRedirectUri());
// ... (other null checks)

// Check default values for non-null properties
Assert.assertEquals("api://default", kindeOAuth2Properties.getAudience());
Assert.assertNotNull(kindeOAuth2Properties.getPermissionsClaim());

27-40: LGTM: Setter methods are thoroughly tested.

The test covers all important setter methods and verifies that the set values can be correctly retrieved.

Consider the following improvements to enhance the test:

  1. Test edge cases: Add tests for empty strings or special characters in the set values.
  2. Use constants: Define test values as constants at the class level for better maintainability.
  3. Test remaining setters: Add tests for setAuthorizationGrantType(), setPostLogoutRedirectUri(), setProxy(), and setScopes() to ensure complete coverage.

Example of using constants:

private static final String TEST_URI = "https://kinde.com";
private static final String TEST_CLIENT_ID = "client-id";
// ... other constants

@Test
public void testKindeOAuth2Properties() {
    // ... existing setup code

    kindeOAuth2Properties.setRedirectUri(TEST_URI);
    Assert.assertEquals(TEST_URI, kindeOAuth2Properties.getRedirectUri());

    // ... other tests using constants
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 362c75e and 8aaa8b9.

⛔ Files ignored due to path filters (1)
  • kinde-management/pom.xml is excluded by !**/*.xml
📒 Files selected for processing (1)
  • kinde-springboot/kinde-springboot-core/src/test/java/com/kinde/spring/config/KindeOAuth2PropertiesTest.java (1 hunks)
🧰 Additional context used
🔇 Additional comments (1)
kinde-springboot/kinde-springboot-core/src/test/java/com/kinde/spring/config/KindeOAuth2PropertiesTest.java (1)

1-7: LGTM: Package declaration and imports are correct.

The package declaration is consistent with the file path, and all necessary imports are present without any unused ones.

Comment on lines +1 to +44
package com.kinde.spring.config;

import org.junit.Assert;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientProperties;

public class KindeOAuth2PropertiesTest {

@Test
public void testKindeOAuth2Properties() {
OAuth2ClientProperties clientProperties = Mockito.mock(OAuth2ClientProperties.class);
KindeOAuth2Properties kindeOAuth2Properties = new KindeOAuth2Properties(clientProperties);

Assert.assertNull(kindeOAuth2Properties.getRedirectUri());
Assert.assertNull(kindeOAuth2Properties.getClientId());
Assert.assertNull(kindeOAuth2Properties.getClientSecret());
Assert.assertNull(kindeOAuth2Properties.getAuthorizationGrantType());
Assert.assertNull(kindeOAuth2Properties.getDomain());
Assert.assertEquals("api://default",kindeOAuth2Properties.getAudience());
Assert.assertNull(kindeOAuth2Properties.getPostLogoutRedirectUri());
Assert.assertNull(kindeOAuth2Properties.getProxy());
Assert.assertNull(kindeOAuth2Properties.getScopes());

Assert.assertNotNull(kindeOAuth2Properties.getPermissionsClaim());

kindeOAuth2Properties.setRedirectUri("https://kinde.com");
Assert.assertEquals("https://kinde.com",kindeOAuth2Properties.getRedirectUri());

kindeOAuth2Properties.setClientId("client-id");
Assert.assertEquals("client-id",kindeOAuth2Properties.getClientId());

kindeOAuth2Properties.setClientSecret("client-secret");
Assert.assertEquals("client-secret",kindeOAuth2Properties.getClientSecret());

kindeOAuth2Properties.setDomain("https://kinde.com");
Assert.assertEquals("https://kinde.com",kindeOAuth2Properties.getDomain());

kindeOAuth2Properties.setAudience("https://kinde.com/api");
Assert.assertEquals("https://kinde.com/api",kindeOAuth2Properties.getAudience());
}


}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Good start on testing, but room for improvement in coverage and structure.

The test provides a solid foundation for verifying the basic functionality of KindeOAuth2Properties. However, there are several areas where the test can be enhanced:

  1. Comprehensive coverage: Add tests for all setter methods and properties, including those currently not covered (e.g., setScopes(), setProxy()).

  2. Edge case testing: Include tests for potential error cases and invalid inputs to ensure robust behavior.

  3. Test organization: Consider breaking down the single large test method into multiple smaller, focused test methods. This improves readability and makes it easier to identify which specific functionality has failed when a test doesn't pass.

  4. Use of test fixtures: Implement @BeforeEach to set up common test objects, reducing code duplication.

  5. Parameterized tests: For properties that accept various inputs, consider using JUnit's parameterized tests to cover multiple scenarios efficiently.

Here's an example of how you might restructure the tests:

public class KindeOAuth2PropertiesTest {
    private OAuth2ClientProperties clientProperties;
    private KindeOAuth2Properties kindeOAuth2Properties;

    @BeforeEach
    void setUp() {
        clientProperties = Mockito.mock(OAuth2ClientProperties.class);
        kindeOAuth2Properties = new KindeOAuth2Properties(clientProperties);
    }

    @Test
    void testDefaultValues() {
        // Test all properties for their default values
    }

    @Test
    void testSetterMethods() {
        // Test all setter methods
    }

    @ParameterizedTest
    @ValueSource(strings = {"https://kinde.com", "", "invalid-uri"})
    void testSetRedirectUri(String uri) {
        kindeOAuth2Properties.setRedirectUri(uri);
        assertEquals(uri, kindeOAuth2Properties.getRedirectUri());
    }

    // Additional test methods for other properties and edge cases
}

This structure would provide more comprehensive and organized testing for the KindeOAuth2Properties class.

@brettchaldecott
Copy link
Contributor Author

This has been replaced with another pr.

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