mivita/tests/Feature/Payment
2026-02-20 17:55:06 +01:00
..
ConcurrentPaymentTest.php 20-02-2026 2026-02-20 17:55:06 +01:00
PayoneRaceConditionTest.php 20-02-2026 2026-02-20 17:55:06 +01:00
README.md 20-02-2026 2026-02-20 17:55:06 +01:00

Payment Race Condition Tests

Diese Test-Suite überprüft die Behebung von Race Conditions bei der Zahlungsabwicklung und Rechnungsnummernvergabe.

Übersicht

Problem

Wenn mehrere Zahlungen fast gleichzeitig über die Payone API eingehen, konnte es zu Race Conditions kommen:

  • Doppelte Rechnungsnummern
  • Mehrfache Verarbeitung derselben Zahlung
  • Inkonsistente Datenbank-Zustände

Lösung

3-Stufen-Absicherung implementiert:

  1. Database Locking im PayoneController mit lockForUpdate()
  2. Atomic Invoice Number Vergabe mit Transaction + Lock
  3. Double-Check Pattern zur zusätzlichen Absicherung

Test-Dateien

1. ConcurrentPaymentTest.php

Tests für gleichzeitige Rechnungsnummernvergabe:

  • it_generates_unique_invoice_numbers_under_concurrent_load() - Eindeutigkeit bei hoher Last
  • it_atomically_increments_invoice_numbers() - Atomare Inkrementierung
  • it_does_not_skip_invoice_numbers_on_transaction_rollback() - Keine Lücken
  • it_uses_database_locking_for_invoice_numbers() - Lock-Mechanismus
  • it_prevents_double_processing_of_same_payment() - Doppelverarbeitung verhindern
  • it_can_lock_settings_for_update() - Setting-Lock funktioniert
  • it_creates_invoice_numbers_with_correct_format() - Korrekte Formatierung
  • it_handles_rapid_sequential_invoice_creation() - Schnelle Sequenzen
  • it_initializes_invoice_number_if_not_exists() - Initialisierung
  • it_handles_concurrent_transaction_commits() - Gleichzeitige Commits

2. PayoneRaceConditionTest.php

Tests für Payone-spezifische Race Conditions:

  • it_locks_shopping_order_during_payment_processing() - Order wird gelockt
  • it_prevents_double_payment_processing() - Doppelte Zahlung verhindern
  • it_serializes_concurrent_payment_requests() - Serialisierung
  • it_rolls_back_payment_on_error() - Rollback bei Fehler
  • it_tracks_payment_status_transitions() - Status-Übergänge
  • it_handles_concurrent_payments_for_different_orders() - Verschiedene Orders
  • it_isolates_payment_transactions() - Transaction Isolation
  • it_prevents_concurrent_modifications() - Gleichzeitige Änderungen verhindern
  • it_enforces_unique_payment_references() - Eindeutige Referenzen

3. InvoiceServiceTest.php (Unit Tests)

Unit-Tests für Invoice Service:

  • it_gets_current_invoice_number() - Nummer abrufen
  • it_increments_invoice_number() - Inkrementierung
  • it_increments_sequentially() - Sequenzielle Inkrementierung
  • it_formats_invoice_number_with_year_prefix() - Formatierung
  • it_generates_correct_storage_paths() - Storage-Pfade
  • it_generates_correct_filenames() - Dateinamen
  • it_initializes_invoice_number_when_not_exists() - Initialisierung
  • it_uses_transaction_for_invoice_number_increment() - Transaction Usage
  • it_locks_setting_during_increment() - Lock während Increment
  • it_pads_invoice_numbers_correctly() - Korrekte Padding
  • it_returns_zero_when_invoice_number_not_set() - Default-Wert
  • it_handles_rapid_increments_without_gaps() - Keine Lücken
  • it_returns_integer_invoice_number() - Typ-Sicherheit

Tests ausführen

Alle Payment-Tests

./vendor/bin/phpunit tests/Feature/Payment/

Einzelne Test-Datei

./vendor/bin/phpunit tests/Feature/Payment/ConcurrentPaymentTest.php
./vendor/bin/phpunit tests/Feature/Payment/PayoneRaceConditionTest.php
./vendor/bin/phpunit tests/Unit/Services/InvoiceServiceTest.php

Einzelner Test

./vendor/bin/phpunit --filter it_generates_unique_invoice_numbers_under_concurrent_load

Mit Coverage

./vendor/bin/phpunit --coverage-html coverage/ tests/Feature/Payment/

Mit Pest (falls verwendet)

./vendor/bin/pest tests/Feature/Payment/

Wichtige Hinweise

Database Transactions

Alle Tests verwenden DatabaseTransactions Trait:

  • Änderungen werden nach jedem Test automatisch zurückgerollt
  • Tests sind isoliert und beeinflussen sich nicht gegenseitig
  • Keine manuelle Datenbank-Bereinigung nötig

Test-Daten

Tests erstellen eigene Test-Daten:

  • ShoppingOrder, ShoppingPayment, ShoppingUser
  • Setting für invoice-number
  • Alle Daten werden nach Test automatisch entfernt

Performance

Tests simulieren Concurrent Scenarios:

  • Verwenden separate DB-Transactions
  • Testen Lock-Mechanismen
  • Prüfen auf Race Conditions

Continuous Integration

Diese Tests sollten Teil der CI/CD Pipeline sein:

# .github/workflows/tests.yml
- name: Run Payment Tests
  run: ./vendor/bin/phpunit tests/Feature/Payment/

Monitoring in Production

Nach Deployment überwachen:

  1. Log-Einträge prüfen:

    grep "Error:2008" storage/logs/laravel.log
    
  2. Rechnungsnummern auf Lücken prüfen:

    SELECT * FROM user_invoices 
    ORDER BY number 
    -- Prüfe auf Lücken in der Sequenz
    
  3. Doppelte Rechnungsnummern prüfen:

    SELECT full_number, COUNT(*) 
    FROM user_invoices 
    GROUP BY full_number 
    HAVING COUNT(*) > 1;
    

Troubleshooting

Test schlägt fehl: "Database not configured"

cp .env.example .env.testing
php artisan key:generate --env=testing

Test schlägt fehl: "Setting not found"

Tests initialisieren automatisch - prüfe Migration:

php artisan migrate --env=testing

Test schlägt fehl: "Foreign key constraint"

Prüfe, ob alle Referenzen korrekt erstellt werden:

php artisan migrate:fresh --env=testing

Weiterführende Informationen

  • Code-Änderungen: Siehe Git Commit mit Tag race-condition-fix
  • Dokumentation: /dev/[DATUM]/payment-race-condition-fix.md
  • Issue: Siehe entsprechendes GitHub Issue

Erstellt: Januar 2026 Autor: Claude AI Assistant Status: Production Ready