""" Unit tests — Oracle error code → HTTP status mapping. Tests _handle_oracle_error() directly. No live Oracle connection required. Covered mappings: ORA-20001 … ORA-20999 → HTTP 422 (business errors from RAISE_APPLICATION_ERROR) ORA-12541/12170/12154/12560 → HTTP 503 (Oracle network / TNS unreachable) ORA-01017 → HTTP 500 (bad credentials) ORA-00942 → HTTP 500 (missing object / grant) ORA- → HTTP 500 (unexpected error) """ import pytest from unittest.mock import MagicMock from fastapi import HTTPException from backend.modules.service_auto.services.comanda_service import _handle_oracle_error def _make_oracle_error(code: int, msg: str = "test error"): """ Build a minimal mock that mimics oracledb.DatabaseError structure. _handle_oracle_error only accesses e.args[0].code and e.args[0].message, so a MagicMock is sufficient — no live oracledb import needed. """ err_obj = MagicMock() err_obj.code = code err_obj.message = f"ORA-{code:05d}: {msg}" exc = MagicMock() exc.args = (err_obj,) return exc # --------------------------------------------------------------------------- # Parametrised: code → expected HTTP status + fragment in detail # --------------------------------------------------------------------------- @pytest.mark.parametrize("code, status, detail_fragment", [ # Business errors — RAISE_APPLICATION_ERROR range (20001, 422, "mesaj business 20001"), (20500, 422, "mesaj business 20500"), (20999, 422, "mesaj business 20999"), # Oracle network / TNS unreachable (12541, 503, "indisponibil"), (12170, 503, "indisponibil"), (12154, 503, "indisponibil"), (12560, 503, "indisponibil"), # Credential / config errors (1017, 500, "configurare"), # Missing object / grant (942, 500, "internă"), # Catch-all unexpected errors (4031, 500, "neașteptată"), # ORA-04031: unable to allocate memory (600, 500, "neașteptată"), # ORA-00600: internal error ]) def test_error_mapping(code, status, detail_fragment): msg = f"mesaj business {code}" if 20001 <= code <= 20999 else "test error" exc = _make_oracle_error(code, msg) with pytest.raises(HTTPException) as exc_info: _handle_oracle_error(exc) http_exc = exc_info.value assert http_exc.status_code == status, ( f"ORA-{code:05d} → expected HTTP {status}, got {http_exc.status_code}" ) assert detail_fragment in http_exc.detail, ( f"ORA-{code:05d} detail: expected '{detail_fragment}' in '{http_exc.detail}'" ) # --------------------------------------------------------------------------- # ORA-20xxx: verify ORA prefix is stripped from business message # --------------------------------------------------------------------------- def test_20001_strips_ora_prefix(): """The 422 detail must not contain the 'ORA-20001:' prefix.""" exc = _make_oracle_error(20001, "Mai exista o comanda cu numarul P01-42") with pytest.raises(HTTPException) as exc_info: _handle_oracle_error(exc) detail = exc_info.value.detail assert not detail.startswith("ORA-"), ( f"ORA prefix not stripped: '{detail}'" ) assert "Mai exista" in detail # --------------------------------------------------------------------------- # Edge case: missing code attribute (e.g. thin-mode edge case) # --------------------------------------------------------------------------- def test_no_code_attribute_maps_to_500(): """If the error object has no .code, fall through to generic 500.""" err_obj = MagicMock(spec=[]) # spec=[] means NO attributes exc = MagicMock() exc.args = (err_obj,) with pytest.raises(HTTPException) as exc_info: _handle_oracle_error(exc) assert exc_info.value.status_code == 500