From 44b6b29dc5edf1ed00daf377378c187051b76a90 Mon Sep 17 00:00:00 2001 From: Kengne-yvana Date: Thu, 15 Jan 2026 20:19:30 +0100 Subject: [PATCH] FINERACT-2086: Fix ClassCastException in AccountAssociations and add unit tests - Simplified conversion using Number.intValue() to handle Short and Integer types. - Removed redundant null checks as per feedback. - Added unit tests for type-safety verification. --- ...ntAssociationsReadPlatformServiceImpl.java | 4 +- ...sociationsReadPlatformServiceImplTest.java | 78 +++++++++++++++++++ 2 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 fineract-provider/src/test/java/org/apache/fineract/portfolio/account/service/AccountAssociationsReadPlatformServiceImplTest.java diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountAssociationsReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountAssociationsReadPlatformServiceImpl.java index f26eb5984..874462dd9 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountAssociationsReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountAssociationsReadPlatformServiceImpl.java @@ -99,7 +99,9 @@ public class AccountAssociationsReadPlatformServiceImpl implements AccountAssoci final List> statusList = this.jdbcTemplate.queryForList(sql1, savingsId); for (final Map statusMap : statusList) { - AccountAssociationType associationType = AccountAssociationType.fromInt((Integer) statusMap.get("type")); + // Direct conversion using Number handles both Short and Integer safely + final Integer typeValue = ((Number) statusMap.get("type")).intValue(); + final AccountAssociationType associationType = AccountAssociationType.fromInt(typeValue); if (!associationType.isLinkedAccountAssociation() && (Boolean) statusMap.get("active")) { hasActiveAccount = true; break; diff --git a/fineract-provider/src/test/java/org/apache/fineract/portfolio/account/service/AccountAssociationsReadPlatformServiceImplTest.java b/fineract-provider/src/test/java/org/apache/fineract/portfolio/account/service/AccountAssociationsReadPlatformServiceImplTest.java new file mode 100644 index 000000000..b9897acc7 --- /dev/null +++ b/fineract-provider/src/test/java/org/apache/fineract/portfolio/account/service/AccountAssociationsReadPlatformServiceImplTest.java @@ -0,0 +1,78 @@ +/** + /** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.portfolio.account.service; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.lenient; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.springframework.jdbc.core.JdbcTemplate; + +public class AccountAssociationsReadPlatformServiceImplTest { + + @Mock + private JdbcTemplate jdbcTemplate; + + @InjectMocks + private AccountAssociationsReadPlatformServiceImpl service; + + @BeforeEach + public void setUp() { + MockitoAnnotations.initMocks(this); + } + + @Test + public void testRetriveLoanAssociations_HandlesShortFromDatabase() { + List> mockStatusList = new ArrayList<>(); + Map row = new HashMap<>(); + row.put("type", (short) 1); // Simulates the Short/SmallInt + mockStatusList.add(row); + + lenient().when(jdbcTemplate.queryForList(anyString(), any(Object[].class))).thenReturn(mockStatusList); + + assertDoesNotThrow(() -> { + service.retriveLoanAssociations(1L, 1); + }); + } + + @Test + public void testRetriveLoanAssociations_HandlesIntegerFromDatabase() { + List> mockStatusList = new ArrayList<>(); + Map row = new HashMap<>(); + row.put("type", 1); // Simulates standard Integer + mockStatusList.add(row); + + lenient().when(jdbcTemplate.queryForList(anyString(), any(Object[].class))).thenReturn(mockStatusList); + + assertDoesNotThrow(() -> { + service.retriveLoanAssociations(1L, 1); + }); + } +}