Skip to content

test(repositories): pin that UpdateAsync does not rewrite tracked related entities (#361) - #376

Merged
nevridge merged 3 commits into
mainfrom
bugfix/repository-update-tracked-entities
Oct 31, 2026
Merged

nevridge merged 3 commits into
mainfrom
bugfix/repository-update-tracked-entities

Conversation

@nevridge

Copy link
Copy Markdown
Owner

Closes #361

Summary

Issue #361 asked whether UpdateAsync re-marks already-tracked related entities as Modified, which would rewrite the related row and risk a lost update. It was verify-first: characterization tests were written and run before any production change.

Result: Outcome A for both repositories. Neither re-marks the related entity, so no production repository code changes. This matches the EF Core documentation for DbSet.Update (it marks only reachable entities that are not already tracked).

Characterization evidence (AC 4)

Recorded with a SaveChangesInterceptor on SQLite, fresh context per simulated request. Both tests passed on the first run with no production edits.

Scenario Root entity at save Related entity at save Outcome
JournalLogEntryRepository.UpdateAsync, log relinked to a different task (old TaskItem tracked via Include) JournalLogEntry Modified no TaskItem entry recorded A
TaskRepository.UpdateAsync, tracked task edited (Project tracked via Include) TaskItem Modified no Project entry recorded A

The root entity is asserted Modified in both tests, so the recorder demonstrably sees writes and "not written" is meaningful. The relink test also reloads in a fresh context and asserts the FK is the new task id, with the log's navigation still pointing at the old tracked task beforehand.

Changes

  • New TaskFlow.Api.Tests/Repositories/RepositoryUpdateWritesOnlyRootTests.cs: Update_RelinkDoesNotModifyOldTask and Update_TrackedTaskEdit_DoesNotModifyProject, kept as regression guards. Each asserts the related entity is Unchanged before UpdateAsync.
  • JournalLogEntriesControllerRealStackTests.Update_RelinkDoesNotModifyLinkedTasks now also asserts the old task is not written, and the stale "may be marked Modified" comment is corrected.
  • ProjectRepository.UpdateAsync: comment-only fix (it claimed Update would mark every loaded task Modified). No code change.
  • No API, route, schema, migration, client or frontend changes.

Verification

  • dotnet test --project TaskFlow.Api.Tests (CI coverage flags): 782/782 passed, line coverage 94.43% (threshold 75%)
  • dotnet format TaskFlow.sln --verify-no-changes: clean
  • dotnet build TaskFlow.sln -c Release: 0 warnings, 0 errors
  • Mutation check: temporarily marking the old TaskItem / Project Modified in the two repositories makes exactly 3 tests fail (the two new tests and Update_RelinkDoesNotModifyLinkedTasks). Mutations were reverted.
  • Validator: Critical 0 / Important 0 / Minor 0 after one rework pass (explicit tracked-state preconditions and a stale-navigation assertion added).

Notes

  • The scope expansion in Stop repository UpdateAsync from re-marking already-tracked related entities as Modified #361 covered TaskRepository.UpdateAsync; it is not affected. TryAutoCompleteParentAsync goes through the same tracked path and is covered by the tracked-task test.
  • TaskRepository.UpdateAsync still calls Update unconditionally on the root, so a no-op update still writes the task row. That is existing behavior and out of scope here.
  • Merging to main triggers the production deploy; this PR is tests plus a comment only.

@nevridge nevridge left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review: 💬 Comments

No issues found in this diff.


Reviewed at 7e10e6a · findings from pr-review + code-review, verified and triaged by @nevridge with Claude Code

@nevridge
nevridge merged commit f8a6968 into main Oct 31, 2026
15 checks passed
@nevridge
nevridge deleted the bugfix/repository-update-tracked-entities branch October 31, 2026 01:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Stop repository UpdateAsync from re-marking already-tracked related entities as Modified

1 participant