ezgg-lan-manager/testing/unittests/AccountingServiceTests.py
tcprod a419ee8885 Replace float with Decimal for price calculations
Fix Decimal precision issue

Fix Decimal precision issue

Fix Decimal precision issue

Fix old prices for tickets

Fix Decimal precision issue
2025-02-07 23:20:57 +01:00

114 lines
4.5 KiB
Python

import unittest
from datetime import datetime
from unittest.mock import MagicMock, AsyncMock
from decimal import Decimal
from src.ez_lan_manager.services.AccountingService import AccountingService, InsufficientFundsError
from src.ez_lan_manager.types.Transaction import Transaction
class AccountingServiceTests(unittest.IsolatedAsyncioTestCase):
def setUp(self) -> None:
self.mock_database_service = MagicMock()
self.mock_database_service.add_transaction = AsyncMock()
self.accounting_service = AccountingService(self.mock_database_service)
def test_importing_unit_under_test_works(self) -> None:
"""
This test asserts that the object produced in setUp is AccountingService object,
if that fails, there is no reason to execute any other test.
"""
self.assertIsInstance(self.accounting_service, AccountingService)
def test_making_string_from_euro_value_works_correctly(self) -> None:
test_value = Decimal("134.66")
expected_result = "134.66 €"
self.assertEqual(expected_result, AccountingService.make_euro_string_from_decimal(test_value))
def test_making_euro_string_from_negative_value_works_correctly(self) -> None:
test_value = Decimal("-997.41")
expected_result = "-997.41 €"
self.assertEqual(expected_result, AccountingService.make_euro_string_from_decimal(test_value))
def test_making_euro_string_from_less_than_ten_cents_works_correctly(self) -> None:
test_value = Decimal("0.04")
expected_result = "0.04 €"
self.assertEqual(expected_result, AccountingService.make_euro_string_from_decimal(test_value))
async def test_get_balance_correctly_adds_up_transactions(self) -> None:
self.mock_database_service.get_all_transactions_for_user = AsyncMock(return_value=[
Transaction(
user_id=0,
value=Decimal("0.05"),
is_debit=True,
reference="",
transaction_date=datetime.now()
),
Transaction(
user_id=0,
value=Decimal("0.99"),
is_debit=False,
reference="",
transaction_date=datetime.now()
),
Transaction(
user_id=0,
value=Decimal("1.01"),
is_debit=False,
reference="",
transaction_date=datetime.now()
),
Transaction(
user_id=0,
value=Decimal("0.77"),
is_debit=True,
reference="",
transaction_date=datetime.now()
),
])
expected_result = Decimal("1.18")
actual_result = await self.accounting_service.get_balance(0)
self.assertEqual(expected_result, actual_result)
async def test_trying_to_remove_more_than_is_on_account_balance_raises_exception(self) -> None:
user_balance = Decimal("1.00")
balance_to_remove = Decimal("1.01")
self.mock_database_service.get_all_transactions_for_user = AsyncMock(return_value=[
Transaction(
user_id=0,
value=user_balance,
is_debit=False,
reference="",
transaction_date=datetime.now()
)
])
with self.assertRaises(InsufficientFundsError):
await self.accounting_service.remove_balance(0, balance_to_remove, "TestRef")
async def test_trying_to_remove_less_than_is_on_account_balance_spawns_correct_transaction(self) -> None:
user_balance = Decimal("1.01")
balance_to_remove = Decimal("1.00")
reference = "Yey, a reference"
self.mock_database_service.get_all_transactions_for_user = AsyncMock(return_value=[
Transaction(
user_id=123,
value=user_balance,
is_debit=False,
reference="",
transaction_date=datetime.now()
)
])
await self.accounting_service.remove_balance(123, balance_to_remove, reference)
# Async unittest API is still not perfect for retrieving a call value. So we force it to hand it over.
last_transaction: Transaction = self.mock_database_service.add_transaction.call_args_list[-1].args[-1]
self.assertEqual(123, last_transaction.user_id)
self.assertEqual(balance_to_remove, last_transaction.value)
self.assertEqual(True, last_transaction.is_debit)
self.assertEqual(reference, last_transaction.reference)