Skip to content

update jwtutil#302

Open
msslulu wants to merge 2 commits intoopentiny:developfrom
msslulu:feat/test
Open

update jwtutil#302
msslulu wants to merge 2 commits intoopentiny:developfrom
msslulu:feat/test

Conversation

@msslulu
Copy link
Copy Markdown
Contributor

@msslulu msslulu commented Apr 17, 2026

English | 简体中文

PR

PR Checklist

Please check if your PR fulfills the following requirements:

  • The commit message follows our Commit Message Guidelines
  • Tests for the changes have been added (for bug fixes / features)
  • Docs have been added / updated (for bug fixes / features)
  • Built its own designer, fully self-validated

PR Type

What kind of change does this PR introduce?

  • Bugfix
  • Feature
  • Code style update (formatting, local variables)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • CI related changes
  • Documentation content changes
  • Other... Please describe:

Background and solution

What is the current behavior?

Issue Number: N/A

What is the new behavior?

Does this PR introduce a breaking change?

  • Yes
  • No

Other information

Summary by CodeRabbit

  • Tests

    • Added comprehensive test coverage for dynamic model operations, including schema management (create/drop/initialize tables) and data operations (query, count, pagination, and CRUD operations).
  • Refactor

    • Updated secret key configuration to require explicit environment variable setup. The system now depends entirely on the SECRET_STRING environment variable being present; missing configuration will result in initialization failure.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 17, 2026

Walkthrough

JwtUtil.java removes the hardcoded DEFAULT_SECRET constant and changes getSecretString() to return the environment variable directly without fallback logic, making the secret key retrieval dependent entirely on the SECRET_STRING environment variable. A comprehensive test suite for DynamicModelService is added, covering table operations, CRUD functionality, and querying with mocked dependencies.

Changes

Cohort / File(s) Summary
JWT Configuration
base/src/main/java/com/tinyengine/it/login/utils/JwtUtil.java
Removed hardcoded DEFAULT_SECRET constant and eliminated Optional fallback logic from getSecretString(), now returning System.getenv("SECRET_STRING") directly. Fails with NullPointerException if environment variable is absent instead of using default.
Dynamic Model Service Tests
base/src/test/java/com/tinyengine/it/dynamic/service/DynamicModelServiceTest.java
Added comprehensive JUnit test class with 15 test methods covering dynamic table creation/dropping, initialization, CRUD operations, dynamic querying, and paginated querying. Uses Mockito mocks for JdbcTemplate, NamedParameterJdbcTemplate, and LoginUserContext, with ReflectUtil for field injection.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A secret springs forth, no longer hidden away,
Environment whispers where the JWT shall play,
Tests bloom like carrots in a garden so bright,
Mock data dancing through the dynamic night,
Coverage grows fluffy, our work takes its flight! 🥕

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 5.26% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'update jwtutil' is vague and does not clearly convey the significance of the changes: removing hardcoded secrets and creating a new test suite for DynamicModelService. Revise the title to reflect the main changes, such as 'Remove hardcoded JWT secret and add DynamicModelService tests' or focus on the primary objective if applicable.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

Copy link
Copy Markdown

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
base/src/main/java/com/tinyengine/it/login/utils/JwtUtil.java (1)

48-55: ⚠️ Potential issue | 🟠 Major

NPE risk and missing key validation after removing default secret.

With DEFAULT_SECRET removed, if SECRET_STRING is unset getSecretString() returns null and getSecretKey() throws an opaque NullPointerException on .getBytes() — every token issue/validate path (including validateToken) will then fail with a generic exception rather than a clear configuration error. Additionally, Keys.hmacShaKeyFor requires the key to be at least 32 bytes for HS256; a short SECRET_STRING will throw WeakKeyException at runtime with no early feedback.

Please fail fast at startup (or on first use) with a descriptive message, e.g.:

🛡️ Suggested guard
 private static String getSecretString() {
-    return System.getenv("SECRET_STRING");
+    String secret = System.getenv("SECRET_STRING");
+    if (secret == null || secret.isEmpty()) {
+        throw new IllegalStateException(
+            "Environment variable SECRET_STRING is not set; cannot initialize JWT signing key.");
+    }
+    if (secret.getBytes(java.nio.charset.StandardCharsets.UTF_8).length < 32) {
+        throw new IllegalStateException(
+            "SECRET_STRING must be at least 32 bytes for HS256.");
+    }
+    return secret;
 }

Also note that Optional (line 32) is now unused after this change.

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

In `@base/src/main/java/com/tinyengine/it/login/utils/JwtUtil.java` around lines
48 - 55, getSecretString can return null and getSecretKey currently calls
.getBytes() blindly and passes the result to Keys.hmacShaKeyFor which will
either NPE or throw WeakKeyException later; change getSecretKey to validate the
environment value from getSecretString() (non-null/non-empty after trim) and
ensure its byte length is >= 32 (or the algorithm's minimum) and throw an
IllegalStateException (or similar) with a clear message like "SECRET_STRING must
be set and at least 32 bytes" so the application fails fast; perform this check
inside getSecretKey (or during startup initialization) so validateToken paths
don't get opaque NPEs, and remove the now-unused Optional import/field
referenced on line 32.
🧹 Nitpick comments (1)
base/src/test/java/com/tinyengine/it/dynamic/service/DynamicModelServiceTest.java (1)

21-21: Avoid wildcard imports in test code.

import java.util.*; (and the static org.junit.jupiter.api.Assertions.* / org.mockito.Mockito.* wildcards above) make it harder to see which symbols the test actually depends on and can shadow names when the class grows. Most style guides (and typical project checkstyle configs) disallow them — prefer explicit imports.

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

In
`@base/src/test/java/com/tinyengine/it/dynamic/service/DynamicModelServiceTest.java`
at line 21, Replace the wildcard imports in DynamicModelServiceTest (e.g.,
import java.util.*; and any static wildcards like
org.junit.jupiter.api.Assertions.* and org.mockito.Mockito.*) with explicit
imports for only the symbols the test actually uses — for example import
java.util.List, java.util.Arrays, java.util.Optional (or other specific types
used) and static imports such as org.junit.jupiter.api.Assertions.assertEquals,
assertTrue, assertThrows and org.mockito.Mockito.when,
org.mockito.Mockito.verify — by opening DynamicModelServiceTest, identifying the
concrete types and static methods referenced and adding those explicit imports,
removing the wildcard lines.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@base/src/test/java/com/tinyengine/it/dynamic/service/DynamicModelServiceTest.java`:
- Around line 329-341: The testCreateData test stubs the wrong JdbcTemplate
overload (a non-existent three-arg variant) so the stub never matches the actual
call; update the stub to match the real call used by
dynamicModelService.createData by stubbing
jdbcTemplate.update(PreparedStatementCreator, KeyHolder) (e.g.
when(jdbcTemplate.update(any(PreparedStatementCreator.class),
any(KeyHolder.class))).thenReturn(1)) and adjust the verify to match that
signature (verify(jdbcTemplate).update(any(PreparedStatementCreator.class),
any(KeyHolder.class))); also ensure loginUserContext.getLoginUserId() remains
stubbed and assert the real returned Map contents (or remove the duplicate test
altogether and keep a single correct test for createData) so
assertNotNull(result) is meaningful.
- Around line 187-202: The test stubs two calls to
namedParameterJdbcTemplate.queryForList(String, Map) but the second when(...)
overwrites the first, so the data branch in DynamicModelService.queryWithPage
isn't exercised; update the test in DynamicModelServiceTest to stub the two
calls in order — use
Mockito.when(...).thenReturn(firstDataList).thenReturn(countList) or use
doReturn(firstDataList).doReturn(countList).when(namedParameterJdbcTemplate).queryForList(anyString(),
anyMap()) so the first call returns the row data
(List.of(Map.of("id",1,"name","test_name"))) and the second returns the count
(List.of(Map.of("count",1L))); alternatively, distinguish stubs by matching the
SQL string argument if you prefer, ensuring the sequence matches the actual call
order in queryWithPage.
- Around line 43-51: Remove the duplicate MockitoAnnotations.openMocks(this)
call in DynamicModelServiceTest.setUp and drop the three
ReflectUtil.setFieldValue(...) calls for jdbcTemplate, loginUserContext and
namedParameterJdbcTemplate because `@InjectMocks` on dynamicModelService already
performs constructor injection; either store the AutoCloseable returned by the
single openMocks call and close it in an `@AfterEach` method, or replace manual
initialization with `@ExtendWith`(MockitoExtension.class) on the test class to
handle mock lifecycle automatically.
- Around line 238-247: The Mockito matcher Optional.ofNullable(any()) is used
incorrectly in DynamicModelServiceTest when stubbing jdbcTemplate.queryForList
and jdbcTemplate.update; replace those wrapped matchers with the simple any()
matcher so mocks match the production calls that pass single Long/Object
parameters (update all occurrences noted: the queryForList stubs around
dynamicModelService.getDataById and the jdbcTemplate.update stubs at the other
referenced test lines); ensure you use any() for the parameter arguments in the
when(...) and verify(...) calls targeting jdbcTemplate so Mockito matchers
operate correctly.

---

Outside diff comments:
In `@base/src/main/java/com/tinyengine/it/login/utils/JwtUtil.java`:
- Around line 48-55: getSecretString can return null and getSecretKey currently
calls .getBytes() blindly and passes the result to Keys.hmacShaKeyFor which will
either NPE or throw WeakKeyException later; change getSecretKey to validate the
environment value from getSecretString() (non-null/non-empty after trim) and
ensure its byte length is >= 32 (or the algorithm's minimum) and throw an
IllegalStateException (or similar) with a clear message like "SECRET_STRING must
be set and at least 32 bytes" so the application fails fast; perform this check
inside getSecretKey (or during startup initialization) so validateToken paths
don't get opaque NPEs, and remove the now-unused Optional import/field
referenced on line 32.

---

Nitpick comments:
In
`@base/src/test/java/com/tinyengine/it/dynamic/service/DynamicModelServiceTest.java`:
- Line 21: Replace the wildcard imports in DynamicModelServiceTest (e.g., import
java.util.*; and any static wildcards like org.junit.jupiter.api.Assertions.*
and org.mockito.Mockito.*) with explicit imports for only the symbols the test
actually uses — for example import java.util.List, java.util.Arrays,
java.util.Optional (or other specific types used) and static imports such as
org.junit.jupiter.api.Assertions.assertEquals, assertTrue, assertThrows and
org.mockito.Mockito.when, org.mockito.Mockito.verify — by opening
DynamicModelServiceTest, identifying the concrete types and static methods
referenced and adding those explicit imports, removing the wildcard lines.
🪄 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: d97a2ed7-32b6-4f7c-baf5-c56c81cbb0d9

📥 Commits

Reviewing files that changed from the base of the PR and between 0cad53a and d52fa92.

📒 Files selected for processing (2)
  • base/src/main/java/com/tinyengine/it/login/utils/JwtUtil.java
  • base/src/test/java/com/tinyengine/it/dynamic/service/DynamicModelServiceTest.java

Comment on lines +43 to +51
@BeforeEach
void setUp() {
MockitoAnnotations.openMocks(this);
MockitoAnnotations.openMocks(this);
ReflectUtil.setFieldValue(dynamicModelService, "jdbcTemplate", jdbcTemplate);
ReflectUtil.setFieldValue(dynamicModelService, "loginUserContext", loginUserContext);
ReflectUtil.setFieldValue(dynamicModelService, "namedParameterJdbcTemplate", namedParameterJdbcTemplate);

}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Redundant openMocks call and unnecessary ReflectUtil usage.

  • Line 45–46: MockitoAnnotations.openMocks(this) is invoked twice; the second call creates a new set of mocks that are then discarded, and leaks the first AutoCloseable. Keep one call (and ideally close it in @AfterEach, or switch to @ExtendWith(MockitoExtension.class)).
  • Lines 47–49: DynamicModelService uses Lombok @RequiredArgsConstructor over final fields (see DynamicModelService.java:32-39), so @InjectMocks already performs constructor injection with the three mocks. The ReflectUtil.setFieldValue(...) calls are redundant, and if the constructor injection ever silently fails (e.g. a mock is unnamed), reflection will mask that failure.
♻️ Proposed simplification
-    `@BeforeEach`
-    void setUp() {
-        MockitoAnnotations.openMocks(this);
-        MockitoAnnotations.openMocks(this);
-        ReflectUtil.setFieldValue(dynamicModelService, "jdbcTemplate", jdbcTemplate);
-        ReflectUtil.setFieldValue(dynamicModelService, "loginUserContext", loginUserContext);
-        ReflectUtil.setFieldValue(dynamicModelService, "namedParameterJdbcTemplate", namedParameterJdbcTemplate);
-
-    }
+    `@BeforeEach`
+    void setUp() {
+        MockitoAnnotations.openMocks(this);
+    }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@BeforeEach
void setUp() {
MockitoAnnotations.openMocks(this);
MockitoAnnotations.openMocks(this);
ReflectUtil.setFieldValue(dynamicModelService, "jdbcTemplate", jdbcTemplate);
ReflectUtil.setFieldValue(dynamicModelService, "loginUserContext", loginUserContext);
ReflectUtil.setFieldValue(dynamicModelService, "namedParameterJdbcTemplate", namedParameterJdbcTemplate);
}
`@BeforeEach`
void setUp() {
MockitoAnnotations.openMocks(this);
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@base/src/test/java/com/tinyengine/it/dynamic/service/DynamicModelServiceTest.java`
around lines 43 - 51, Remove the duplicate MockitoAnnotations.openMocks(this)
call in DynamicModelServiceTest.setUp and drop the three
ReflectUtil.setFieldValue(...) calls for jdbcTemplate, loginUserContext and
namedParameterJdbcTemplate because `@InjectMocks` on dynamicModelService already
performs constructor injection; either store the AutoCloseable returned by the
single openMocks call and close it in an `@AfterEach` method, or replace manual
initialization with `@ExtendWith`(MockitoExtension.class) on the test class to
handle mock lifecycle automatically.

Comment on lines +187 to +202
List<Map<String, Object>> mockData = new ArrayList<>();
mockData.add(Map.of("id", 1, "name", "test_name"));

when(namedParameterJdbcTemplate.queryForList(anyString(), anyMap())).thenReturn(mockData);
when(namedParameterJdbcTemplate.queryForList(anyString(), anyMap())).thenReturn(List.of(Map.of("count", 1L)));

// Act
Map<String, Object> result = dynamicModelService.queryWithPage(dto);

// Assert
assertNotNull(result);
assertTrue((Boolean) result.get("success"));
assertEquals(1L, result.get("total"));
assertEquals(1, ((List<?>) result.get("data")).size());
verify(namedParameterJdbcTemplate, times(2)).queryForList(anyString(), anyMap());
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

queryWithPage test: second stubbing overrides the first — data branch is never exercised.

Both when(...) calls on lines 190 and 191 target the exact same method signature queryForList(String, Map), so Mockito replaces the first stub with the second. Both the data query and the count query inside queryWithPage will now return [{count=1}], so result.get("data") depends on how the service interprets that single row — the assertions pass only incidentally and the test does not actually validate pagination.

Use sequential stubbing (order must match the production call order) or distinguish by SQL:

♻️ Proposed fix
-        when(namedParameterJdbcTemplate.queryForList(anyString(), anyMap())).thenReturn(mockData);
-        when(namedParameterJdbcTemplate.queryForList(anyString(), anyMap())).thenReturn(List.of(Map.of("count", 1L)));
+        when(namedParameterJdbcTemplate.queryForList(anyString(), anyMap()))
+            .thenReturn(mockData)                       // first call: data page
+            .thenReturn(List.of(Map.of("count", 1L)));  // second call: total count

Confirm the actual call order in queryWithPage before finalizing.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
List<Map<String, Object>> mockData = new ArrayList<>();
mockData.add(Map.of("id", 1, "name", "test_name"));
when(namedParameterJdbcTemplate.queryForList(anyString(), anyMap())).thenReturn(mockData);
when(namedParameterJdbcTemplate.queryForList(anyString(), anyMap())).thenReturn(List.of(Map.of("count", 1L)));
// Act
Map<String, Object> result = dynamicModelService.queryWithPage(dto);
// Assert
assertNotNull(result);
assertTrue((Boolean) result.get("success"));
assertEquals(1L, result.get("total"));
assertEquals(1, ((List<?>) result.get("data")).size());
verify(namedParameterJdbcTemplate, times(2)).queryForList(anyString(), anyMap());
}
List<Map<String, Object>> mockData = new ArrayList<>();
mockData.add(Map.of("id", 1, "name", "test_name"));
when(namedParameterJdbcTemplate.queryForList(anyString(), anyMap()))
.thenReturn(mockData) // first call: data page
.thenReturn(List.of(Map.of("count", 1L))); // second call: total count
// Act
Map<String, Object> result = dynamicModelService.queryWithPage(dto);
// Assert
assertNotNull(result);
assertTrue((Boolean) result.get("success"));
assertEquals(1L, result.get("total"));
assertEquals(1, ((List<?>) result.get("data")).size());
verify(namedParameterJdbcTemplate, times(2)).queryForList(anyString(), anyMap());
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@base/src/test/java/com/tinyengine/it/dynamic/service/DynamicModelServiceTest.java`
around lines 187 - 202, The test stubs two calls to
namedParameterJdbcTemplate.queryForList(String, Map) but the second when(...)
overwrites the first, so the data branch in DynamicModelService.queryWithPage
isn't exercised; update the test in DynamicModelServiceTest to stub the two
calls in order — use
Mockito.when(...).thenReturn(firstDataList).thenReturn(countList) or use
doReturn(firstDataList).doReturn(countList).when(namedParameterJdbcTemplate).queryForList(anyString(),
anyMap()) so the first call returns the row data
(List.of(Map.of("id",1,"name","test_name"))) and the second returns the count
(List.of(Map.of("count",1L))); alternatively, distinguish stubs by matching the
SQL string argument if you prefer, ensuring the sequence matches the actual call
order in queryWithPage.

Comment on lines +238 to +247
when(jdbcTemplate.queryForList(anyString(), Optional.ofNullable(any()))).thenReturn(mockResult);

// Act
Map<String, Object> result = dynamicModelService.getDataById(modelId, id);

// Assert
assertNotNull(result);
assertEquals("test_name", result.get("name"));
verify(jdbcTemplate, times(1)).queryForList(anyString(), Optional.ofNullable(any()));
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
rg -nP -C2 'jdbcTemplate\.(queryForList|update)\s*\(' base/src/main/java/com/tinyengine/it/dynamic/service/DynamicModelService.java

Repository: opentiny/tiny-engine-backend-java

Length of output: 1355


🏁 Script executed:

cat -n base/src/test/java/com/tinyengine/it/dynamic/service/DynamicModelServiceTest.java | sed -n '230,350p'

Repository: opentiny/tiny-engine-backend-java

Length of output: 4583


🏁 Script executed:

cat -n base/src/test/java/com/tinyengine/it/dynamic/service/DynamicModelServiceTest.java | sed -n '350,360p'

Repository: opentiny/tiny-engine-backend-java

Length of output: 341


🏁 Script executed:

rg -n 'import.*jdbcTemplate|import.*JdbcTemplate' base/src/test/java/com/tinyengine/it/dynamic/service/DynamicModelServiceTest.java

Repository: opentiny/tiny-engine-backend-java

Length of output: 209


🏁 Script executed:

rg -n -A10 'public.*getDataById|public.*deleteDataById' base/src/main/java/com/tinyengine/it/dynamic/service/DynamicModelService.java | head -60

Repository: opentiny/tiny-engine-backend-java

Length of output: 876


🏁 Script executed:

cat -n base/src/main/java/com/tinyengine/it/dynamic/service/DynamicModelService.java | sed -n '640,645p'

Repository: opentiny/tiny-engine-backend-java

Length of output: 370


🏁 Script executed:

rg -n 'queryForList|\.update\(' base/src/main/java/com/tinyengine/it/dynamic/service/DynamicModelService.java | grep -E '\.toArray|Object\[\]'

Repository: opentiny/tiny-engine-backend-java

Length of output: 206


🏁 Script executed:

rg -n -B2 'jdbcTemplate\.(queryForList|update)' base/src/main/java/com/tinyengine/it/dynamic/service/DynamicModelService.java

Repository: opentiny/tiny-engine-backend-java

Length of output: 1017


🏁 Script executed:

python3 << 'EOF'
# Let's trace what the actual parameter types are in the production code
production_calls = {
    "line_586": "queryForList(sql, id)",  # id is Long
    "line_642": "update(sql, id)",        # id is Long  
    "line_169": "update(sql, values.toArray())",  # Object[]
    "line_623": "update(sql.toString(), params.toArray())",  # Object[]
}

test_stubs = {
    "lines_238_246": "queryForList(anyString(), Optional.ofNullable(any()))",
    "lines_275_283": "update(anyString(), Optional.ofNullable(any()))",
    "lines_349_353": "update(anyString(), Optional.ofNullable(any()))",
}

print("Production code parameter types:")
print("- queryForList(String, Long) - matches test at lines 238, 246")
print("- update(String, Long) - matches test at lines 275, 283, 349, 353")
print("- update(String, Object[]) - different overload")
print()
print("Test stub matcher issues:")
print("- Optional.ofNullable(any()) is INVALID matcher syntax")
print("- Should be any() for single parameter (Long)")
print("- Should be any(Object[].class) for array parameter")
EOF

Repository: opentiny/tiny-engine-backend-java

Length of output: 465


Fix invalid Mockito matcher usage: replace Optional.ofNullable(any()) with appropriate matchers.

Optional.ofNullable(any()) wraps the matcher incorrectly, evaluating it outside Mockito's context. The production code calls these methods with single Long parameters, not arrays.

Correct fixes:

  • Lines 238, 246 (queryForList): Use any() instead
  • Lines 275, 283, 349, 353 (update with single parameter): Use any() instead

Example:

-        when(jdbcTemplate.queryForList(anyString(), Optional.ofNullable(any()))).thenReturn(mockResult);
+        when(jdbcTemplate.queryForList(anyString(), any())).thenReturn(mockResult);
...
-        verify(jdbcTemplate, times(1)).update(anyString(), Optional.ofNullable(any())).thenReturn(1);
+        verify(jdbcTemplate, times(1)).update(anyString(), any());

Note: The method calls at lines 169 and 623 in production use Object[] parameters, but no test mocks those overloads with this bug.

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

In
`@base/src/test/java/com/tinyengine/it/dynamic/service/DynamicModelServiceTest.java`
around lines 238 - 247, The Mockito matcher Optional.ofNullable(any()) is used
incorrectly in DynamicModelServiceTest when stubbing jdbcTemplate.queryForList
and jdbcTemplate.update; replace those wrapped matchers with the simple any()
matcher so mocks match the production calls that pass single Long/Object
parameters (update all occurrences noted: the queryForList stubs around
dynamicModelService.getDataById and the jdbcTemplate.update stubs at the other
referenced test lines); ensure you use any() for the parameter arguments in the
when(...) and verify(...) calls targeting jdbcTemplate so Mockito matchers
operate correctly.

Comment on lines +329 to +341
@Test
void testCreateData() {
DynamicInsert dataDto = new DynamicInsert();
dataDto.setNameEn("test_table");
dataDto.setParams(Map.of("name", "test"));

when(loginUserContext.getLoginUserId()).thenReturn("1");
when(jdbcTemplate.update(any(), any(PreparedStatementCreator.class), any())).thenReturn(1);

Map<String, Object> result = dynamicModelService.createData(dataDto);
assertNotNull(result);
verify(jdbcTemplate, times(1)).update(any(PreparedStatementCreator.class), any());
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

testCreateData stubs a non-matching overload and will not verify what it claims.

Line 336 stubs jdbcTemplate.update(any(), any(PreparedStatementCreator.class), any()) with three arguments, but JdbcTemplate has no 3-arg update overload that accepts PreparedStatementCreator in the middle position. Either this fails to compile/resolves to an unintended varargs overload, or simply never matches the call performed in createData (which uses update(PreparedStatementCreator, KeyHolder), as correctly verified on line 340). The assertNotNull(result) assertion is therefore meaningless.

This whole test* block (lines 287–354) also largely duplicates the earlier createDynamicTable / dropDynamicTable / dynamicQuery / createData / deleteDataById tests — consider removing the duplicates and keeping a single, correct version per scenario.

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

In
`@base/src/test/java/com/tinyengine/it/dynamic/service/DynamicModelServiceTest.java`
around lines 329 - 341, The testCreateData test stubs the wrong JdbcTemplate
overload (a non-existent three-arg variant) so the stub never matches the actual
call; update the stub to match the real call used by
dynamicModelService.createData by stubbing
jdbcTemplate.update(PreparedStatementCreator, KeyHolder) (e.g.
when(jdbcTemplate.update(any(PreparedStatementCreator.class),
any(KeyHolder.class))).thenReturn(1)) and adjust the verify to match that
signature (verify(jdbcTemplate).update(any(PreparedStatementCreator.class),
any(KeyHolder.class))); also ensure loginUserContext.getLoginUserId() remains
stubbed and assert the real returned Map contents (or remove the duplicate test
altogether and keep a single correct test for createData) so
assertNotNull(result) is meaningful.

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