feat(realestate): naver 워커 listings-ingest(파싱→upsert→매칭→알림)

This commit is contained in:
2026-07-10 00:31:42 +09:00
parent f931c496d8
commit 13e3e558af
2 changed files with 87 additions and 1 deletions

View File

@@ -0,0 +1,46 @@
import os, importlib
from unittest.mock import patch
from fastapi.testclient import TestClient
def _client(monkeypatch):
monkeypatch.setenv("INTERNAL_API_KEY", "SECRET")
from app import auth as _a
importlib.reload(_a)
from app.main import app
return TestClient(app)
_ARTICLE = {"articleNo": "N100", "tradeTypeName": "전세", "dealOrWarrantPrc": "2억 9,000",
"area2": "42.5", "floorInfo": "5/15", "articleName": "OO아파트",
"buildingName": "OO", "cortarNo": "1159010100"}
def test_ingest_auth(monkeypatch):
c = _client(monkeypatch)
# 헤더 없음 — FastAPI Header(...)는 dependency 실행 전 자체 검증하므로 422.
# test_internal_targets.py의 동일 패턴과 일치(같은 서비스 선례).
assert c.post("/api/internal/realestate/listings-ingest", json={"batches": []}).status_code in (401, 422)
assert c.post("/api/internal/realestate/listings-ingest",
headers={"X-Internal-Key": "WRONG"}, json={"batches": []}).status_code == 401
def test_ingest_upserts_and_matches(monkeypatch):
c = _client(monkeypatch)
with patch("app.internal_router.notify_new_listings", return_value={"sent": 1, "sent_ids": [1]}) as noti:
r = c.post("/api/internal/realestate/listings-ingest",
headers={"X-Internal-Key": "SECRET"},
json={"fetched_at": "2026-07-09T00:00:00Z",
"batches": [{"dong": "신대방동", "articles": [_ARTICLE]}]})
assert r.status_code == 200
body = r.json()
assert body["received"] == 1 and body["new"] == 1 and body["matched"] == 1
assert noti.call_count == 1
# 저장 확인
from app import db
ls = db.get_listings()
assert any(l["article_no"] == "N100" and l["dong"] == "신대방동" for l in ls)
def test_ingest_idempotent(monkeypatch):
c = _client(monkeypatch)
payload = {"batches": [{"dong": "신대방동", "articles": [_ARTICLE]}]}
with patch("app.internal_router.notify_new_listings", return_value={"sent": 0}):
c.post("/api/internal/realestate/listings-ingest", headers={"X-Internal-Key": "SECRET"}, json=payload)
r2 = c.post("/api/internal/realestate/listings-ingest", headers={"X-Internal-Key": "SECRET"}, json=payload)
assert r2.json()["new"] == 0 # 재push → 신규 0