Skip to content

Defer reactive cleanup on testServer() exit for the 1.14.0 release#4396

Draft
cpsievert wants to merge 3 commits into
mainfrom
defer-testserver-reactive-cleanup
Draft

Defer reactive cleanup on testServer() exit for the 1.14.0 release#4396
cpsievert wants to merge 3 commits into
mainfrom
defer-testserver-reactive-cleanup

Conversation

@cpsievert

Copy link
Copy Markdown
Collaborator

Why this matters

#4372 makes a closing session destroy the reactives bound to it. Because testServer() closes its mock session on exit, reactives created inside a module under test are now torn down the moment the testServer() block returns. Three CRAN reverse dependencies — blockr.core, blockr.dock, and teal.slice — read such reactives after the testServer() block and now fail with "... its module session has been destroyed".

To avoid breaking them in the 1.14.0 release, this temporarily reverts the test harness to its pre-#4372 behavior of leaving reactives intact on close.

Scope and safety

The change comments out a single line — invokeDestroyCallbacks("") — in MockShinySession$close(). The real ShinySession (ShinySession$wsClosed()) still destroys reactives on close, so application behavior is unchanged; only testServer()/MockShinySession is affected.

This is deliberately temporary. A detailed note at the change site explains how and when to re-enable: once the affected maintainers have been notified to adapt their tests (create session-independent reactives with withReactiveDomain(NULL, ...), or read/snapshot reactive state inside the testServer() block), uncomment the line and the paired tests, which are commented out behind the same searchable marker in tests/testthat/test-destroy.R and tests/testthat/test-test-server.R.

Verification

A new test in test-test-server.R reproduces the failure (a reactiveValues created inside a module is read after testServer() returns) and passes with the change. Both downstream failure shapes (returning a reactive from a testServer() helper; an external object holding a reactive created inside testServer()) were confirmed fixed against this branch.

#4372 made a closing session destroy its bound reactives. testServer()
closes its mock session on exit, so reactives created inside a module
under test are destroyed as soon as the block returns. Several CRAN
packages (blockr.core, blockr.dock, teal.slice) read such reactives after
the testServer() block and broke with destroyedReactiveError.

Comment out invokeDestroyCallbacks("") in MockShinySession$close() for the
1.14.0 release so the test harness reverts to pre-#4372 behavior. The real
ShinySession still destroys on close, so app behavior is unchanged. A
detailed note in the source explains how/when to re-enable after notifying
the affected maintainers; the paired close-destroys tests are commented out
with the same marker.
Comment thread R/mock-session.R
Comment thread tests/testthat/test-test-server.R Outdated
Comment thread R/mock-session.R
# paired tests in tests/testthat/test-destroy.R (search for this same
# marker) and tests/testthat/test-test-server.R.
#
# private$invokeDestroyCallbacks("")

@cpsievert cpsievert Jun 1, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

After #4395

Suggested change
# private$invokeDestroyCallbacks("")
# private$invokeDestroyCallbacks(allowRoot = TRUE)

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.

1 participant