Opening a transaction pins the connection, so a read inside one goes to the primary regardless of what the router intended.
DB::transaction(function () {
$report = Order::from('orders')->heavyAggregate(); // PRIMARY
$this->store($report);
});
// which is correct — a replica read inside a write
// transaction would see a different snapshot — and means
// wrapping a report in a transaction quietly moves it
// onto the primary.
// and the wrapper nobody notices: a test with
// RefreshDatabase runs every test inside one.
The test-suite case is the one that hides this: every test runs inside a transaction, so the read routing is never exercised and the first time it matters is production. Asserting on the connection name in one test is a cheap way to keep the routing honest.