[EPAC-1875]: Add integration tests for POST /api/v1/device/register handler#459
Conversation
Five integration tests under //go:build integration verify the real device_subscriptions upsert SQL — happy path insert, ON CONFLICT update, missing token 400, malformed JSON 400 with no DB write, and empty follow-lists stored as non-NULL empty arrays. Also wires epac/_testdb into go.mod so the harness is available to the device-register test binary.
…efore t.Cleanup
The test registered a t.Cleanup(restoreSpeechVectors) callback but also used
defer conn.Close(ctx). Defers fire when the function returns, before t.Cleanup
runs, so restoreSpeechVectors received an already-closed connection ("conn closed").
testdb.Connect already registers its own t.Cleanup to close the connection, so
the defer was redundant and harmful. Removing it restores the correct LIFO
cleanup order: restoreSpeechVectors runs first, conn.Close runs last.
Pre-existing failure on main (4 consecutive failures before EPAC-1875 PR).
|
CI fix pushed — commit The Root cause (pre-existing on main — 4 consecutive failures before this PR opened): Fix: removed the redundant No production code changed. Device-register integration tests are unaffected. |
|
Symphony expected a reviewer-bot review for the current autonomous PR head within the configured SLA window, but none was found.
|
There was a problem hiding this comment.
ReviewAutonomousPR
- Verdict:
approve - Reviewer boundary:
review_only - Acceptance criteria coverage: covered=5, missing=0, unclear=0
Summary
The patch adds the requested DB-backed integration tests for POST /api/v1/device/register, including upsert and malformed-input behavior, and uses the shared integration harness correctly; overall it satisfies the acceptance criteria and is mergeable.
Actionable findings
- risk / follow_up — Malformed-JSON no-write assertion is table-scoped instead of token-scoped (
backend/device-register/main_integration_test.go:173)TestDeviceRegisterMalformedJSON_Returns400assertsCOUNT(*) FROM device_subscriptions == 0after sending invalid JSON. This is broader than necessary and can yield brittle failures if other fixture/test rows are present in the same shared table state. A token-specific absence check is safer and still verifies the contract.- Actionability:
follow_up
Acceptance criteria coverage
- covered — TestDeviceRegisterHappyPath_InsertsRow
- Implemented integration test posts valid payload, expects 200, reads back
device_subscriptions, and validates stored token/member/topics/bills. - Actionability:
none - Evidence: backend/device-register/main_integration_test.go
- Implemented integration test posts valid payload, expects 200, reads back
- covered — TestDeviceRegisterUpsert_SameTokenUpdates
- Implemented by seeding a row for a token, posting again with the same token, asserting single-row count and updated
topic_ids. - Actionability:
none - Evidence: backend/device-register/main_integration_test.go
- Implemented by seeding a row for a token, posting again with the same token, asserting single-row count and updated
- covered — TestDeviceRegisterMissingToken_Returns400
- Implemented with
{}payload and asserts HTTP 400 plus error text containingtoken. - Actionability:
none - Evidence: backend/device-register/main_integration_test.go
- Implemented with
- covered — TestDeviceRegisterMalformedJSON_Returns400
- Implemented malformed JSON path and checks for HTTP 400 and no writes, with an assertion that is currently table-wide rather than token-scoped.
- Actionability:
follow_up - Evidence: backend/device-register/main_integration_test.go
- Suggested follow-up: Scope no-write assertion to test token or fixture isolation
- covered — TestDeviceRegisterEmptyFollows_StoresEmptyArrays
- Implemented with missing
topic_ids/bill_ids, asserts stored arrays are non-nil and length zero. - Actionability:
none - Evidence: backend/device-register/main_integration_test.go
- Implemented with missing
Why
The device-register upsert SQL — including the
ON CONFLICT DO UPDATEclause andTEXT[]array storage fortopic_ids/bill_ids— was only exercised by mocked-repository tests. Schema drift, array serialization bugs, or a removedON CONFLICTclause would not fail existing tests. This PR adds five DB-backed integration tests that catch those failures at PR time.What changed
backend/device-register/main_integration_test.go(new): five integration tests under//go:build integration, each wrapped in_testdb.WithTxfor rollback isolation.TestDeviceRegisterHappyPath_InsertsRow— full payload insert, asserts all fields written.TestDeviceRegisterUpsert_SameTokenUpdates— seeds a row then re-POSTs; asserts exactly one row with updatedtopic_ids.TestDeviceRegisterMissingToken_Returns400— empty JSON body; asserts 400 with"token"in error message.TestDeviceRegisterMalformedJSON_Returns400— non-JSON body; asserts 400 and zero rows written.TestDeviceRegisterEmptyFollows_StoresEmptyArrays— omitted arrays; asserts non-NULL{}stored, not NULL.backend/device-register/go.mod: addedepac/_testdb v0.0.0require + replace directive (mirrors pattern inlive-status/go.mod).Trade-offs not taken
t.Parallel()— the harness shares one migrated schema andsync.Once; parallel tests would race onmigrated.Do. Sequential is consistent with all other integration tests in the repo.granularityJSONB readback — the AC does not require it and the column defaults to{}. The core correctness (array types, upsert) is what matters here.Test plan
CI runs this automatically via the
backend-integration-testsworkflow.Verification
go build ./...— cleango vet -tags=integration ./...— cleanResolves EPAC-1875
Reviewer-Boundary: review-only