feat(s4): infrastructure persistence tests — 32 adapter ITs (STA-135)#126
Conversation
|
Caution Review failedPull request was closed or merged during review WalkthroughAdds five new integration test classes covering persistence for chain transfers, transfer participants, lifecycle events, wallet balances, and wallets, plus a DB migration converting several NUMERIC(20,0) columns to BIGINT to align with Java Long mapping. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested labels
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@blockchain-custody/blockchain-custody/src/integration-test/java/com/stablecoin/payments/custody/infrastructure/persistence/TransferParticipantPersistenceAdapterIT.java`:
- Around line 104-112: The test currently only checks row count; instead
retrieve the saved participants via
adapter.findByTransferId(transfer.transferId()) and assert their ParticipantType
values match ParticipantType.values() (e.g., compare sets or sorted lists) to
ensure enum mapping is persisted correctly; locate where
adapter.save(TransferParticipant.create(...)) is used and replace/extend the
final assertion to verify the retrieved participants' getType() (or equivalent)
equals the expected ParticipantType values rather than only checking size.
In
`@blockchain-custody/blockchain-custody/src/integration-test/java/com/stablecoin/payments/custody/infrastructure/persistence/WalletPersistenceAdapterIT.java`:
- Around line 69-82: The test should verify that the returned wallet is the
active one, not just the count: after calling
adapter.findByChainIdAndPurpose(CHAIN_BASE, PURPOSE_ON_RAMP) assert that the
single result matches the saved active wallet (the variable active returned by
adapter.save(anActiveWallet())) or at minimum assert that result.isActive() /
!result.isDeactivated() is true; update the test method
shouldFindByChainIdAndPurposeOnlyActiveWallets to fetch the single wallet from
results and compare its identity/fields against active (or assert it's not
deactivated) so a returned deactivated row would fail.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 0c058517-60b7-4090-95c5-2dc04ff444ec
📒 Files selected for processing (6)
blockchain-custody/blockchain-custody/src/integration-test/java/com/stablecoin/payments/custody/infrastructure/persistence/ChainTransferPersistenceAdapterIT.javablockchain-custody/blockchain-custody/src/integration-test/java/com/stablecoin/payments/custody/infrastructure/persistence/TransferLifecycleEventPersistenceAdapterIT.javablockchain-custody/blockchain-custody/src/integration-test/java/com/stablecoin/payments/custody/infrastructure/persistence/TransferParticipantPersistenceAdapterIT.javablockchain-custody/blockchain-custody/src/integration-test/java/com/stablecoin/payments/custody/infrastructure/persistence/WalletBalancePersistenceAdapterIT.javablockchain-custody/blockchain-custody/src/integration-test/java/com/stablecoin/payments/custody/infrastructure/persistence/WalletPersistenceAdapterIT.javablockchain-custody/blockchain-custody/src/main/resources/db/migration/V4__fix_numeric_to_bigint.sql
| for (var type : ParticipantType.values()) { | ||
| adapter.save(TransferParticipant.create( | ||
| transfer.transferId(), type, | ||
| FROM_ADDRESS, wallet.walletId(), | ||
| new BigDecimal("100.00"), "USDC")); | ||
| } | ||
|
|
||
| assertThat(adapter.findByTransferId(transfer.transferId())) | ||
| .hasSize(ParticipantType.values().length); |
There was a problem hiding this comment.
Assert the persisted enum values, not just the row count.
Lines 111-112 only prove that one row was written per loop iteration. A broken enum mapping that stores multiple ParticipantType values as the same database value would still pass. Assert the retrieved participant types match ParticipantType.values().
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@blockchain-custody/blockchain-custody/src/integration-test/java/com/stablecoin/payments/custody/infrastructure/persistence/TransferParticipantPersistenceAdapterIT.java`
around lines 104 - 112, The test currently only checks row count; instead
retrieve the saved participants via
adapter.findByTransferId(transfer.transferId()) and assert their ParticipantType
values match ParticipantType.values() (e.g., compare sets or sorted lists) to
ensure enum mapping is persisted correctly; locate where
adapter.save(TransferParticipant.create(...)) is used and replace/extend the
final assertion to verify the retrieved participants' getType() (or equivalent)
equals the expected ParticipantType values rather than only checking size.
| @Test | ||
| @DisplayName("should find by chain id and purpose only active wallets") | ||
| void shouldFindByChainIdAndPurposeOnlyActiveWallets() { | ||
| var active = adapter.save(anActiveWallet()); | ||
| var deactivated = Wallet.create( | ||
| CHAIN_BASE, "0xDeactivatedWallet999", "0xDeactivatedWallet999", | ||
| WalletTier.HOT, WalletPurpose.ON_RAMP, "fireblocks", "vault-002", | ||
| StablecoinTicker.of("USDC")); | ||
| var savedDeactivated = adapter.save(deactivated); | ||
| adapter.save(savedDeactivated.deactivate()); | ||
|
|
||
| var results = adapter.findByChainIdAndPurpose(CHAIN_BASE, PURPOSE_ON_RAMP); | ||
| assertThat(results).hasSize(1); | ||
| } |
There was a problem hiding this comment.
Assert the returned wallet is the active one.
Lines 80-81 only verify cardinality. If the query returns the deactivated row and drops the active one, this test still passes. Compare the single result with active, or at least assert it is not deactivated.
Suggested assertion
var results = adapter.findByChainIdAndPurpose(CHAIN_BASE, PURPOSE_ON_RAMP);
- assertThat(results).hasSize(1);
+ assertThat(results).singleElement()
+ .usingRecursiveComparison()
+ .ignoringFieldsOfTypes(Instant.class)
+ .isEqualTo(active);📝 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.
| @Test | |
| @DisplayName("should find by chain id and purpose only active wallets") | |
| void shouldFindByChainIdAndPurposeOnlyActiveWallets() { | |
| var active = adapter.save(anActiveWallet()); | |
| var deactivated = Wallet.create( | |
| CHAIN_BASE, "0xDeactivatedWallet999", "0xDeactivatedWallet999", | |
| WalletTier.HOT, WalletPurpose.ON_RAMP, "fireblocks", "vault-002", | |
| StablecoinTicker.of("USDC")); | |
| var savedDeactivated = adapter.save(deactivated); | |
| adapter.save(savedDeactivated.deactivate()); | |
| var results = adapter.findByChainIdAndPurpose(CHAIN_BASE, PURPOSE_ON_RAMP); | |
| assertThat(results).hasSize(1); | |
| } | |
| `@Test` | |
| `@DisplayName`("should find by chain id and purpose only active wallets") | |
| void shouldFindByChainIdAndPurposeOnlyActiveWallets() { | |
| var active = adapter.save(anActiveWallet()); | |
| var deactivated = Wallet.create( | |
| CHAIN_BASE, "0xDeactivatedWallet999", "0xDeactivatedWallet999", | |
| WalletTier.HOT, WalletPurpose.ON_RAMP, "fireblocks", "vault-002", | |
| StablecoinTicker.of("USDC")); | |
| var savedDeactivated = adapter.save(deactivated); | |
| adapter.save(savedDeactivated.deactivate()); | |
| var results = adapter.findByChainIdAndPurpose(CHAIN_BASE, PURPOSE_ON_RAMP); | |
| assertThat(results).singleElement() | |
| .usingRecursiveComparison() | |
| .ignoringFieldsOfTypes(Instant.class) | |
| .isEqualTo(active); | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@blockchain-custody/blockchain-custody/src/integration-test/java/com/stablecoin/payments/custody/infrastructure/persistence/WalletPersistenceAdapterIT.java`
around lines 69 - 82, The test should verify that the returned wallet is the
active one, not just the count: after calling
adapter.findByChainIdAndPurpose(CHAIN_BASE, PURPOSE_ON_RAMP) assert that the
single result matches the saved active wallet (the variable active returned by
adapter.save(anActiveWallet())) or at minimum assert that result.isActive() /
!result.isDeactivated() is true; update the test method
shouldFindByChainIdAndPurposeOnlyActiveWallets to fetch the single wallet from
results and compare its identity/fields against active (or assert it's not
deactivated) so a returned deactivated row would fail.
ChainTransferPersistenceAdapterIT (10 tests): CRUD, findByPaymentIdAndType, findByStatus, full happy path, resubmission path, failure path, return transfer with parent id, nullable chain id. WalletPersistenceAdapterIT (7 tests): CRUD, findByAddress, findByChainIdAndPurpose (only active), deactivate update, unique constraint. WalletBalancePersistenceAdapterIT (8 tests): CRUD, findByWalletIdAndStablecoin, findByWalletId, reserve, release + confirmDebit, unique constraint, decimal precision (8 places). TransferParticipantPersistenceAdapterIT (4 tests): CRUD, multiple participants (INPUT/OUTPUT/FEE), all participant types enum round-trip. TransferLifecycleEventPersistenceAdapterIT (4 tests): CRUD, multiple events, event with participant details. V4 migration: fix NUMERIC(20,0) → BIGINT for block_number, nonce, last_indexed_block, current_nonce (Hibernate maps Long to BIGINT). Closes STA-135 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
84654e2 to
ae06ee3
Compare
Summary
Total: 281 tests (249 unit + 32 IT)
Test plan
Closes STA-135
🤖 Generated with Claude Code
Summary by CodeRabbit