Files
billing/billing_app/tests.py
2026-01-07 09:17:45 +07:00

180 lines
6.0 KiB
Python

import json
from unittest.mock import patch, MagicMock
from graphene_django.utils.testing import GraphQLTestCase
from .models import Account
import uuid
class BillingGraphQLTests(GraphQLTestCase):
GRAPHQL_URL = '/graphql/public/'
@patch('billing_app.schemas.tigerbeetle_client')
def test_create_transfer_new_accounts(self, mock_tb_client):
"""
Tests that a transfer is created successfully and that new accounts
are created lazily in both the local DB and in TigerBeetle.
"""
# Configure the mock to return no errors
mock_tb_client.create_accounts.return_value = []
mock_tb_client.create_transfers.return_value = []
debit_account_id = str(uuid.uuid4())
credit_account_id = str(uuid.uuid4())
amount = 100
ledger = 1
code = 200
# Ensure accounts do not exist locally
self.assertEqual(Account.objects.count(), 0)
response = self.query(
'''
mutation createTransfer(
$debitAccountId: String!,
$creditAccountId: String!,
$amount: Int!,
$ledger: Int!,
$code: Int!
) {
createTransfer(
debitAccountId: $debitAccountId,
creditAccountId: $creditAccountId,
amount: $amount,
ledger: $ledger,
code: $code
) {
success
message
transferId
}
}
''',
variables={
'debitAccountId': debit_account_id,
'creditAccountId': credit_account_id,
'amount': amount,
'ledger': ledger,
'code': code
}
)
self.assertResponseNoErrors(response)
content = json.loads(response.content)
result = content['data']['createTransfer']
self.assertTrue(result['success'])
self.assertIsNotNone(result['transferId'])
self.assertEqual(result['message'], 'Transfer completed successfully.')
# Verify local accounts were created
self.assertEqual(Account.objects.count(), 2)
self.assertTrue(Account.objects.filter(uuid=debit_account_id).exists())
self.assertTrue(Account.objects.filter(uuid=credit_account_id).exists())
# Verify TigerBeetle client was called correctly
mock_tb_client.create_accounts.assert_called_once()
self.assertEqual(len(mock_tb_client.create_accounts.call_args[0][0]), 2) # Called with 2 accounts
mock_tb_client.create_transfers.assert_called_once()
self.assertEqual(len(mock_tb_client.create_transfers.call_args[0][0]), 1) # Called with 1 transfer
transfer_arg = mock_tb_client.create_transfers.call_args[0][0][0]
self.assertEqual(transfer_arg.amount, amount)
@patch('billing_app.schemas.tigerbeetle_client')
def test_create_transfer_existing_accounts(self, mock_tb_client):
"""
Tests that a transfer is created successfully with existing accounts
and that `create_accounts` is not called.
"""
mock_tb_client.create_transfers.return_value = []
debit_account_id = uuid.uuid4()
credit_account_id = uuid.uuid4()
# Pre-populate the local database
Account.objects.create(uuid=debit_account_id)
Account.objects.create(uuid=credit_account_id)
self.assertEqual(Account.objects.count(), 2)
response = self.query(
'''
mutation createTransfer(
$debitAccountId: String!,
$creditAccountId: String!,
$amount: Int!,
$ledger: Int!,
$code: Int!
) {
createTransfer(
debitAccountId: $debitAccountId,
creditAccountId: $creditAccountId,
amount: $amount,
ledger: $ledger,
code: $code
) {
success
message
transferId
}
}
''',
variables={
'debitAccountId': str(debit_account_id),
'creditAccountId': str(credit_account_id),
'amount': 50,
'ledger': 1,
'code': 201
}
)
self.assertResponseNoErrors(response)
# Verify that create_accounts was NOT called
mock_tb_client.create_accounts.assert_not_called()
# Verify that create_transfers WAS called
mock_tb_client.create_transfers.assert_called_once()
def test_create_transfer_invalid_uuid(self):
"""
Tests that the mutation fails gracefully with an invalid UUID.
"""
response = self.query(
'''
mutation createTransfer(
$debitAccountId: String!,
$creditAccountId: String!,
$amount: Int!,
$ledger: Int!,
$code: Int!
) {
createTransfer(
debitAccountId: $debitAccountId,
creditAccountId: $creditAccountId,
amount: $amount,
ledger: $ledger,
code: $code
) {
success
message
transferId
}
}
''',
variables={
'debitAccountId': 'not-a-uuid',
'creditAccountId': str(uuid.uuid4()),
'amount': 50,
'ledger': 1,
'code': 202
}
)
self.assertResponseNoErrors(response)
content = json.loads(response.content)
result = content['data']['createTransfer']
self.assertFalse(result['success'])
self.assertEqual(result['message'], 'Invalid account ID format. Must be a valid UUID.')