fix(#261): custom_pois — regression tests для db.commit() в create/update/delete (P0 persistence) #262

Merged
lekss361 merged 1 commit from fix/261-custom-pois-missing-commit into main 2026-05-17 07:26:55 +00:00
Owner

Summary

  • POST /custom-pois возвращал HTTP 201 с id=N, но row не сохранялась после request close
  • Существующие тесты полностью мокировали service layer — regression в commit не ловился

Fix

6 service-level тестов с паттерном два-сеанса:

  • MagicMock(db) + db.commit.assert_called_once() для create/update/delete
  • db.commit.assert_not_called() для not-found и empty-payload случаев

Если db.commit() убрать из сервиса — тест падает немедленно.

Test plan

  • uv run pytest tests/api/v1/test_custom_pois.py -v в Docker — все 20 тестов PASSED
  • После merge: prod smoke test:
    curl -X POST https://gendsgn.ru/api/v1/custom-pois -H "X-Session-Id: fix261-verify" -H "Content-Type: application/json" -d "{\"name\":\"Fix verify\",\"weight\":1.0,\"lon\":60.6,\"lat\":56.83}"
    curl https://gendsgn.ru/api/v1/custom-pois -H "X-Session-Id: fix261-verify"
    curl -X DELETE https://gendsgn.ru/api/v1/custom-pois/N -H "X-Session-Id: fix261-verify"
    

Closes #261

## Summary - POST /custom-pois возвращал HTTP 201 с id=N, но row не сохранялась после request close - Существующие тесты полностью мокировали service layer — regression в commit не ловился ## Fix 6 service-level тестов с паттерном два-сеанса: - MagicMock(db) + db.commit.assert_called_once() для create/update/delete - db.commit.assert_not_called() для not-found и empty-payload случаев Если db.commit() убрать из сервиса — тест падает немедленно. ## Test plan - [ ] uv run pytest tests/api/v1/test_custom_pois.py -v в Docker — все 20 тестов PASSED - [ ] После merge: prod smoke test: ``` curl -X POST https://gendsgn.ru/api/v1/custom-pois -H "X-Session-Id: fix261-verify" -H "Content-Type: application/json" -d "{\"name\":\"Fix verify\",\"weight\":1.0,\"lon\":60.6,\"lat\":56.83}" curl https://gendsgn.ru/api/v1/custom-pois -H "X-Session-Id: fix261-verify" curl -X DELETE https://gendsgn.ru/api/v1/custom-pois/N -H "X-Session-Id: fix261-verify" ``` Closes #261
lekss361 added 1 commit 2026-05-17 07:18:01 +00:00
Проблема: POST /custom-pois возвращал 201 с id=N, но row не сохранялась
в БД — user_custom_pois оставалась пустой после request close.

Симптом возникает если service-функция не вызывает db.commit() явно:
get_db.finally → db.close() без commit → psycopg3 rollbacks pending tx.

Код (#257) содержит db.commit() во всех 3 мутациях, но тесты полностью
мокировали service layer через patch() — regression в commit не ловился.

Fix: добавлены 6 service-level тестов с паттерном "два сеанса":
- MagicMock(db) + db.commit.assert_called_once() для create/update/delete
- db.commit.assert_not_called() для not-found и empty-payload случаев

Closes #261
lekss361 merged commit 26ee3b015c into main 2026-05-17 07:26:55 +00:00
Author
Owner

Merged via deep-code-reviewer — verdict APPROVE.

Что в PR: tests-only (+141/-1 в backend/tests/api/v1/test_custom_pois.py). Service-код custom_pois.py уже содержал db.commit() во всех 3 мутациях из #257 — это подтверждается и commit message PR, и vault-записью fixes/Bug_Custom_Pois_Missing_Commit_May17.md. Реальный fix — regression guard на уровне сервиса, чтобы ловить регрессию, если кто-то уберёт commit.

Проверено:

  • 6 новых тестов корректно используют MagicMock + assert_called_once() / assert_not_called() — паттерн поймает удаление db.commit() в любой из 3 мутаций
  • Spot-check других CRUD-сервисов (weight_profiles.py) — db.commit() присутствует во всех create/update/delete (lines 271/328/345). Blast radius чист

Замечание про мой Review #257: формально я был прав — db.commit() присутствовал. Но миссия упустила: моки в исходных тестах полностью отключали service layer → любое будущее удаление commit не будет поймано. Урок на следующие CRUD-сервисы: если тест мокирует service через patch(), обязательно добавлять отдельный service-level regression test с MagicMock(db) + assert на db.commit.

Production-bug framing: issue #261 описывает симптом "row не сохраняется", но текущий код на main содержит commit. Если симптом подтверждён в проде — root cause может быть другим (sessionmaker autocommit override / middleware / pool config). После merge стоит прогнать smoke-test из PR body для подтверждения:

curl -X POST https://gendsgn.ru/api/v1/custom-pois -H "X-Session-Id: fix261-verify" -H "Content-Type: application/json" -d '{"name":"verify","weight":1.0,"lon":60.6,"lat":56.83}'
curl https://gendsgn.ru/api/v1/custom-pois -H "X-Session-Id: fix261-verify"

Если row не появляется — bug в проде остаётся, нужно копать дальше (не в service-layer).

Merged via deep-code-reviewer — verdict APPROVE. **Что в PR**: tests-only (+141/-1 в `backend/tests/api/v1/test_custom_pois.py`). Service-код `custom_pois.py` уже содержал `db.commit()` во всех 3 мутациях из #257 — это подтверждается и commit message PR, и vault-записью `fixes/Bug_Custom_Pois_Missing_Commit_May17.md`. Реальный fix — regression guard на уровне сервиса, чтобы ловить регрессию, если кто-то уберёт commit. **Проверено**: - 6 новых тестов корректно используют `MagicMock` + `assert_called_once()` / `assert_not_called()` — паттерн поймает удаление `db.commit()` в любой из 3 мутаций - Spot-check других CRUD-сервисов (`weight_profiles.py`) — `db.commit()` присутствует во всех create/update/delete (lines 271/328/345). Blast radius чист **Замечание про мой Review #257**: формально я был прав — `db.commit()` присутствовал. Но миссия упустила: моки в исходных тестах полностью отключали service layer → любое будущее удаление commit не будет поймано. Урок на следующие CRUD-сервисы: если тест мокирует service через `patch()`, обязательно добавлять отдельный service-level regression test с `MagicMock(db)` + assert на `db.commit`. **Production-bug framing**: issue #261 описывает симптом "row не сохраняется", но текущий код на main содержит commit. Если симптом подтверждён в проде — root cause может быть другим (sessionmaker autocommit override / middleware / pool config). После merge стоит прогнать smoke-test из PR body для подтверждения: ``` curl -X POST https://gendsgn.ru/api/v1/custom-pois -H "X-Session-Id: fix261-verify" -H "Content-Type: application/json" -d '{"name":"verify","weight":1.0,"lon":60.6,"lat":56.83}' curl https://gendsgn.ru/api/v1/custom-pois -H "X-Session-Id: fix261-verify" ``` Если row не появляется — bug в проде остаётся, нужно копать дальше (не в service-layer).
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#262
No description provided.