/* * Copyright (c) 2005-2011 Grameen Foundation USA * All rights reserved. * * Licensed 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. * * See also http://www.apache.org/licenses/LICENSE-2.0.html for an * explanation of the license and how it is applied. */ package org.mifos.framework.util.helpers; import static org.mifos.framework.TestUtils.EURO; import static org.mifos.framework.TestUtils.RUPEE; import java.math.BigDecimal; import java.math.RoundingMode; import junit.framework.Assert; import org.junit.Test; import org.mifos.application.master.business.MifosCurrency; import org.mifos.config.AccountingRules; import org.mifos.config.AccountingRulesConstants; import org.mifos.config.business.MifosConfigurationManager; import org.mifos.core.CurrencyMismatchException; import org.mifos.framework.TestUtils; public class MoneyTest { @Test public void testAdd() { Money money = new Money(RUPEE, "100.0"); Money addendend = new Money(RUPEE, "200.0"); Assert.assertEquals("testing Add, should succeed", new Money(RUPEE, "300.0"), money.add(addendend)); } @Test public void testAddMultipleDecimalAmounts() { Money money = new Money(RUPEE, "0.1"); Money money1 = money.add(new Money(RUPEE, "0.1")); Money money2 = money1.add(new Money(RUPEE, "0.1")); Money money3 = money2.add(new Money(RUPEE, "0.1")); Money money4 = money3.add(new Money(RUPEE, "0.1")); Assert.assertEquals("testing addMultipleDecimalAmounts, should succeed", new Money(RUPEE, "0.5"), money4); } @Test public void testAddWithDiffCurrencies() { Money money = new Money(RUPEE, "100.0"); try { Money addendendWithDiffCurrecny = new Money(EURO, "200"); money.add(addendendWithDiffCurrecny); Assert.fail("testing Add with different currencies should throw an exception."); } catch (CurrencyMismatchException e) { } } @Test public void testSubtract() { Money subtrahend = new Money(RUPEE, "100.0"); Money money = new Money(RUPEE, "200.0"); Assert.assertEquals("testing subtract, should succeed", new Money(RUPEE, "100.0"), money.subtract(subtrahend)); } @Test public void testSubtractWithDiffCurrencies() { Money money = new Money(RUPEE, "100.0"); try { Money subtrahendWithDiffCurrecny = new Money(EURO, "100"); money.subtract(subtrahendWithDiffCurrecny); Assert.fail("testing subtract with different currencies should throw an exception."); } catch (CurrencyMismatchException e) { } } @Test public void testMultiply() { BigDecimal multiplicand = new BigDecimal("10.0"); Money money = new Money(RUPEE, "20.0"); Assert .assertEquals("testing multiply, should succeed", new Money(RUPEE, "200.0"), money .multiply(multiplicand)); } @Test public void testFactorMultiply() { Money money = new Money(RUPEE, "100.0"); Double factor = new Double(1.24); Assert.assertEquals("testing multiply with a factor, should succeed", new Money(RUPEE, "124.0"), money .multiply(factor)); } @Test public void testMultiplyBigDecimal() { Money money = new Money(RUPEE, "100.0"); BigDecimal factor = new BigDecimal(1.24); Assert.assertEquals("testing multiply with a factor, should succeed", new Money(RUPEE, "124.0"), money .multiply(factor)); } @Test public void testDivideByMoney() { Money dividend = new Money(RUPEE, new BigDecimal(10.0)); Money money = new Money(RUPEE, "20.0"); Assert .assertEquals("testing divide, should succeed", new BigDecimal("2.0000000000000"), money .divide(dividend)); } @Test public void testDivideByBigDecimal() { BigDecimal dividend = new BigDecimal(10.0); Money money = new Money(RUPEE, "20.0"); Assert.assertEquals("testing divide, should succeed", new Money(RUPEE, "2.0"), money.divide(dividend)); } @Test public void testDivideByShort() { Short dividend = new Short("4"); Money money = new Money(RUPEE, "20.0"); Assert.assertEquals("testing divide, should succeed", new Money(RUPEE, "5.00000000000000"), money .divide(dividend)); } @Test public void testDivideByInteger() { Integer dividend = new Integer("3"); Money money = new Money(RUPEE, "20.0"); Money expected = new Money(RUPEE, "6.6666666666667"); Money result = money.divide(dividend); Assert.assertEquals("testing divide, should succeed", expected, result); } @Test public void testDivideRepeating() { BigDecimal dividend = new BigDecimal("3.0"); Money money = new Money(RUPEE, "10.0"); Assert.assertEquals("testing divide, should succeed", new Money(RUPEE, "3.3333333333333"), money .divide(dividend)); money = new Money(RUPEE, "20.0"); Assert.assertEquals("testing divide, should succeed", new Money(RUPEE, "6.6666666666667"), money .divide(dividend)); } @Test public void testDivideWithDiffCurrencies() { Money money = new Money(RUPEE, "20.0"); try { Money dividendWithDiffCurrecny = new Money(EURO, "10"); money.divide(dividendWithDiffCurrecny); Assert.fail("testing divide with different currencies should throw an exception."); } catch (CurrencyMismatchException e) { } } @Test public void testNegate() { Money money = new Money(RUPEE, "20.0"); Assert.assertEquals(new Money(RUPEE, "-20.0"), money.negate()); } @Test public void testRoundUp() { Money money = new Money(RUPEE, "142.34"); Assert.assertEquals(new Money(RUPEE, "143.00"), Money.round(money, money.getCurrency().getRoundingAmount(), RoundingMode.CEILING)); } @Test public void testRoundDown() { Money money = new Money(EURO, "142.34"); Assert.assertEquals(new Money(EURO, "142.00"), Money.round(money, money.getCurrency().getRoundingAmount(), RoundingMode.FLOOR)); } @Test public void testRoundRepeating() { MifosCurrency currency = new MifosCurrency((short) 1, "test", BigDecimal.valueOf(3.0), "USD"); Money money = new Money(currency, "1"); Assert.assertEquals(new Money(currency, "3"), Money.round(money, currency.getRoundingAmount(), RoundingMode.CEILING)); } @Test public void testRoundWhenRoundingOffMultipleIsHundred() { BigDecimal roundingOffMultiple = BigDecimal.valueOf(100); Money roundedMoney = Money.round(new Money(EURO, "1100"), roundingOffMultiple, RoundingMode.CEILING); Assert.assertEquals(new Money(EURO, "1100"), roundedMoney); roundedMoney = Money.round(new Money(EURO, "1101"), roundingOffMultiple, RoundingMode.CEILING); Assert.assertEquals(new Money(EURO, "1200"), roundedMoney); roundedMoney = Money.round(new Money(EURO, "1149"), roundingOffMultiple, RoundingMode.HALF_UP); Assert.assertEquals(new Money(EURO, "1100"), roundedMoney); roundedMoney = Money.round(new Money(EURO, "1150"), roundingOffMultiple, RoundingMode.HALF_UP); Assert.assertEquals(new Money(EURO, "1200"), roundedMoney); roundedMoney = Money.round(new Money(EURO, "1199"), roundingOffMultiple, RoundingMode.FLOOR); Assert.assertEquals(new Money(EURO, "1100"), roundedMoney); roundedMoney = Money.round(new Money(EURO, "1199"), roundingOffMultiple, RoundingMode.FLOOR); Assert.assertEquals(new Money(EURO, "1100"), roundedMoney); } @Test public void testRoundingExceptionWhenRoundingOffMultipleIsZero() { BigDecimal roundingOffMultiple = BigDecimal.valueOf(0); try { Money.round(new Money(EURO, "1100"), roundingOffMultiple, RoundingMode.CEILING); } catch (ArithmeticException e) { } } @Test public void testIsRoundedAmount() { String currencyCodeSuffix = "." + TestUtils.EURO.getCurrencyCode(); MifosConfigurationManager configMgr = MifosConfigurationManager.getInstance(); configMgr.setProperty(AccountingRulesConstants.DIGITS_AFTER_DECIMAL + currencyCodeSuffix, "1"); configMgr.setProperty(AccountingRulesConstants.INITIAL_ROUND_OFF_MULTIPLE + currencyCodeSuffix, "1"); configMgr.setProperty(AccountingRulesConstants.FINAL_ROUND_OFF_MULTIPLE + currencyCodeSuffix, "1"); configMgr.setProperty(AccountingRulesConstants.ADDITIONAL_CURRENCY_CODES, TestUtils.EURO.getCurrencyCode()); try { Assert.assertTrue(MoneyUtils.isRoundedAmount(new Money(EURO, "1"))); Assert.assertFalse(MoneyUtils.isRoundedAmount(new Money(EURO, "1.1"))); Money.setDefaultCurrency(RUPEE); Assert.assertFalse(MoneyUtils.isRoundedAmount(1.1)); } finally { configMgr.clearProperty(AccountingRulesConstants.DIGITS_AFTER_DECIMAL + currencyCodeSuffix); configMgr.clearProperty(AccountingRulesConstants.INITIAL_ROUND_OFF_MULTIPLE + currencyCodeSuffix); configMgr.clearProperty(AccountingRulesConstants.FINAL_ROUND_OFF_MULTIPLE + currencyCodeSuffix); configMgr.clearProperty(AccountingRulesConstants.ADDITIONAL_CURRENCY_CODES); } } @Test public void testDivideMoneyRepeating() { Money dividend = new Money(RUPEE, "3.0"); Money money = new Money(RUPEE, "10.0"); Assert .assertEquals("testing divide, should succeed", new BigDecimal("3.3333333333333"), money .divide(dividend)); } @Test public void testHashCode() { Money money = new Money(RUPEE, "142.34"); BigDecimal amnt = new BigDecimal(142.34); Assert.assertEquals((money.getCurrency().getCurrencyId() * 100 + amnt.intValue()), money.hashCode()); } @Test public void testHashCodeForNullCurrency() { try { Money money = new Money(null, "0"); Assert.assertEquals(0, money.hashCode()); } catch (NullPointerException e) { Assert.assertEquals(e.getLocalizedMessage(), ExceptionConstants.CURRENCY_MUST_NOT_BE_NULL); } } @Test public void testToString() { Money money = new Money(RUPEE, "4456456456.6"); Assert.assertEquals("The toString of money returns : ", "4456456456.6", money.toString(Short.valueOf("1"))); } @Test public void testIsGreaterThan() { Money large = new Money(RUPEE, "10.0"); Money small = new Money(RUPEE, "1.0"); Money same = new Money(RUPEE, "10.0"); Assert.assertTrue("large should be greater than small", large.isGreaterThan(small)); Assert.assertFalse("large should not be greater than itself", large.isGreaterThan(large)); Assert.assertFalse("small should not be greater than large", small.isGreaterThan(large)); Assert.assertFalse("large should not be equal to same", large.isGreaterThan(same)); } @Test public void testIsGreaterThanOrEqual() { Money large = new Money(RUPEE, "10.0"); Money small = new Money(RUPEE, "1.0"); Assert.assertTrue(large.isGreaterThanOrEqual(small)); Assert.assertTrue(large.isGreaterThanOrEqual(large)); Assert.assertFalse(small.isGreaterThanOrEqual(large)); } @Test public void testIsGreaterThanZero() { Money nonZero = new Money(RUPEE, "10.0"); Money zero = new Money(RUPEE, "0.0"); Money lessThanZero = new Money(RUPEE, "-2.0"); Assert.assertTrue(nonZero.isGreaterThanZero()); Assert.assertFalse(lessThanZero.isGreaterThanZero()); Assert.assertFalse(zero.isGreaterThanZero()); } @Test public void testIsGreaterThanOrEqualZero() { Money nonZero = new Money(RUPEE, "10.0"); Money zero = new Money(RUPEE, "0.0"); Money lessThanZero = new Money(RUPEE, "-2.0"); Assert.assertTrue(nonZero.isGreaterThanZero()); Assert.assertFalse(lessThanZero.isGreaterThanOrEqualZero()); Assert.assertTrue(zero.isGreaterThanOrEqualZero()); } @Test public void testIsLessThan() { Money large = new Money(EURO, "10.0"); Money small = new Money(EURO, "1.0"); Assert.assertTrue("small should be less than large", small.isLessThan(large)); Assert.assertFalse("small should not be less than itself", small.isLessThan(small)); Assert.assertFalse("large should not be less than small", large.isLessThan(small)); } @Test public void testIsLessThanOrEqual() { Money large = new Money(RUPEE, "10.0"); Money small = new Money(RUPEE, "1.0"); Money same = new Money(RUPEE, "10.0"); Assert.assertFalse(large.isLessThanOrEqual(small)); Assert.assertTrue(small.isLessThanOrEqual(large)); Assert.assertTrue(small.isLessThanOrEqual(large)); Assert.assertTrue(large.isLessThanOrEqual(same)); } @Test public void testIsLessThanZero() { Money nonZero = new Money(RUPEE, "10.0"); Money zero = new Money(RUPEE); Money lessThanZero = new Money(RUPEE, "-2.0"); Assert.assertFalse(nonZero.isLessThanZero()); Assert.assertTrue(lessThanZero.isLessThanZero()); Assert.assertFalse(zero.isLessThanZero()); } @Test public void testIsLessThanOrEqualZero() { Money nonZero = new Money(RUPEE, "10.0"); Money zero = new Money(RUPEE); Money lessThanZero = new Money(RUPEE, "-2.0"); Assert.assertFalse(nonZero.isLessThanOrEqualZero()); Assert.assertTrue(lessThanZero.isLessThanOrEqualZero()); Assert.assertTrue(zero.isLessThanOrEqualZero()); } @Test public void testIsZero() { Money nonZero = new Money(RUPEE, "10.0"); Money zero = new Money(RUPEE); Money lessThanZero = new Money(RUPEE, "-2.0"); Assert.assertFalse(nonZero.isZero()); Assert.assertFalse(lessThanZero.isZero()); Assert.assertTrue(zero.isZero()); } @Test public void testIsNonZero() { Money nonZero = new Money(RUPEE, "10.0"); Money zero = new Money(RUPEE); Money lessThanZero = new Money(RUPEE, "-2.0"); Assert.assertTrue(nonZero.isNonZero()); Assert.assertTrue(lessThanZero.isNonZero()); Assert.assertFalse(zero.isNonZero()); } @Test public void testIsLessThanForDifferentCurrencies() { Money large = new Money(RUPEE, "10.0"); Money small = new Money(EURO, "1.0"); try { Assert.assertFalse("large should not be less than small", large.isLessThan(small)); Assert.fail("Comparing two different currencies should throw and exceeption"); } catch (RuntimeException e) { } } @Test public void testIsGreaterThanForDifferentCurrencies() { Money large = new Money(RUPEE, "10.0"); Money small = new Money(EURO, "1.0"); try { Assert.assertFalse("large should not be less than small", large.isGreaterThan(small)); Assert.fail("Comparing two different currencies should throw and exceeption"); } catch (RuntimeException e) { } } @Test public void testDetermineWhetherTinyAmount() { Short digitsAfterDecimal = AccountingRules.getDigitsAfterDecimal(); AccountingRules.setDigitsAfterDecimal(Short.valueOf("2")); Money money; money = new Money(RUPEE, "10.5"); org.junit.Assert.assertFalse(money.isTinyAmount()); money = new Money(RUPEE, "0.5"); org.junit.Assert.assertFalse(money.isTinyAmount()); money = new Money(RUPEE, "0.05"); org.junit.Assert.assertFalse(money.isTinyAmount()); money = new Money(RUPEE, "0.005"); org.junit.Assert.assertTrue(money.isTinyAmount()); money = new Money(RUPEE, "-0.005"); org.junit.Assert.assertTrue(money.isTinyAmount()); money = new Money(RUPEE, "-1.0"); org.junit.Assert.assertFalse(money.isTinyAmount()); AccountingRules.setDigitsAfterDecimal(Short.valueOf(digitsAfterDecimal)); } }