test(repo): tighten throw assertions in tests - #2972
VelikovPetar wants to merge 1 commit into
Conversation
…atch Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (10)
Included review availability: Your plan provides up to 4 included reviews per hour; 3 remain after this review. 📝 WalkthroughWalkthroughThe pull request updates Dart test error assertions across client, channel, API, HTTP, token, and WebSocket tests. It adds guidance for synchronous and asynchronous ChangesException Assertion Refactor
Priority: ⬇️ Low Estimated code review effort: 2 (Simple) | ~15 minutes Change: Other Suggested reviewers: Merge Risk: ⚪ Minimal · up to The test refactor strengthens error assertions without changing production behavior. The updated tests and guidance are ready to merge. 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #2972 +/- ##
=======================================
Coverage 75.95% 75.95%
=======================================
Files 447 447
Lines 28870 28870
=======================================
Hits 21928 21928
Misses 6942 6942 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Submit a pull request
Linear: FLU-794
CLA
Description of the pull request
packages/stream_chat/test/asserted thrown errors with a baretry/catchand nofail()on the fall-through path:When the production guard goes away the
catchbody never runs, so the test stays green.grep -rn '\bfail(' packages/*/test/returned zero hits repo-wide, so no instance of this pattern anywhere closed the hole.This converts all 56 such blocks to the
throwsAidiom the suite already uses ~29 times (e.g.channel_test.dart:6153), and adds aTESTING.mdrule so the pattern does not come back.Scale
58
try/catchblocks inpackages/stream_chat/test/; 56 are vacuous with respect to the throw. Two were already correct — they capture the error and assert outside thetry— and are left alone.channel_test.dartstream_http_client_test.dartclient_test.dartauth_interceptor_test.dartgeneral_api_test.darttoken_manager_test.dartwebsocket_test.dartrequests_test.dart,token_test.dartHow this was verified
Every block was mutation-tested in both directions: neutralise the throw source, run that single test before the fix (must pass — proving it was vacuous) and after (must fail — proving the assertion is live). 56/56 in each direction.
Tier-1 blocks were mutated by neutralising the production guard: the
channel.dartsetters, therequests.dart/general_api.dart/token.dart/token_manager.dartasserts, thewebsocket.dartre-entrancy guard, theAuthInterceptorreject paths, andStreamHttpClient's_parseErrorwrapping. The rest were mutated at the production seam — replacing eachrethrowinchannel.dartwith a normal return — which leaves the surrounding state-transition assertions intact and isolates the error contract exactly.Two mutations had to be deepened to mean anything. Deleting the
general_api.dartasserts leaves an unstubbed mock returning null, so the test fails with aTypeError— that is "a different throw appeared", not "the throw was removed"; a faithful returns-normally simulation shows all three blocks are vacuous.token_manager_test:54is the same story: a second, same-typed assert downstream inloadTokenkeeps it green for the wrong reason until both are removed.Production code is untouched — every mutation was reverted, and
git diff HEAD -- packages/stream_chat/libis empty.Two real defects this surfaced
token_test.darthad zero coverage of the guard it names.`.fromRawValue` should throw if does not contain `user_id`passed'bad-token-without-a-user-id', which is not a JWT at all —josethrowsArgumentErrorwhile parsing, and the actual missing-claim guard (theassertattoken.dart:41, anAssertionError) was never reached. The assertion happened to match the wrong error. Split into two tests, one per path.WebSocket.connectand bothpinMessageoverloads returnFuturebut are notasync, so they throw whileexpectLater's argument is being evaluated and the matcher never sees the error. These use the closure form; the oldtry/catchhid the distinction entirely.Two deviations from the fix proposed in FLU-794
throwsA(isA<T>())would have dropped assertions. Several catch bodies assert more than the type (networkError.code,err.message, equality againstStreamChatNetworkError.fromDioException(error)). Those are preserved with.having(...)/allOf(...).auth_interceptor_testkeeps atry/catch. Those four blocks unwrap a private dio type via(e as dynamic).data. They use capture-and-assert-outside instead — the form thestream_chat_flutter/stream_chat_flutter_coresuites already use — which closes the hole without forcing adynamicaccess into a matcher.So six
try/catchblocks remain in the package by design: the two that were already correct, plus those four.Scope
reporather thanllc: this is test-only, changes no package behavior, and therefore takes noCHANGELOG.mdentry per the changelog policy. Thesemantic_changelog_updatejob keys that requirement off the PR scope.Testing
packages/stream_chat: 1922 tests green (1921 before, +1 from thetoken_testsplit).melos run analyze: clean across all packages.dart format: clean on every changed file.Follow-up, deliberately not in this PR
general_api.dart:44,channel.dart:1207,client.dart:2172andrequests.dart:32validate caller input insideasserts, whichSTYLE_GUIDE.mdexplicitly forbids ("Do not use asserts to validate user input or network data (those must throw at runtime)"). Those "should throw" contracts therefore do not exist in release builds at all. Fixing it is a behavior change and needs its own ticket.Screenshots / Videos
Not applicable — test-only change.
🤖 Generated with Claude Code
Summary by CodeRabbit