Skip to content

test: end a request without a handler inside MSW instead of on the network - #747

Merged
Eomdahyeon merged 1 commit into
mainfrom
test/issue-741-no-real-network
Oct 5, 2026
Merged

Eomdahyeon merged 1 commit into
mainfrom
test/issue-741-no-real-network

Conversation

@Eomdahyeon

Copy link
Copy Markdown
Collaborator

Refs #741

#745 의 추적이 잡은 것

#744 의 Coverage gate 잡에서 같은 테스트가 다시 실패했고, 이번에는 [#741] 블록이 찍혔다:

[#741] requests of the failed test, in order:
5ms fetch rejected GET /warehouse/tables: TypeError: fetch failed (cause: AggregateError); signal aborted: false
10ms msw request:start GET /datasets/air
10ms msw request:match GET /datasets/air
11ms msw response:mocked GET /datasets/air
…
44ms msw request:unhandled GET /builds/run-2/spec
86ms fetch rejected GET /builds/run-2/spec: TypeError: fetch failed (cause: AggregateError); signal aborted: false
87ms fetch rejected GET /builds/run-2/stages: TypeError: fetch failed (cause: SocketError: closed); signal aborted: false

핸들러가 등록된 GET /warehouse/tables 가 request:start 없이 fetch failed 로 끝났다. #745 본문이 적은 세 갈래 중 "그 순간 요청이 MSW 를 거치지 않았다" 쪽이다. AggregateError 는 실제 localhost (::1, 127.0.0.1) 연결 시도가 실패할 때의 원인이다.

왜 그럴 수 있는가 (가설)

  • 이 MSW(3.0.2, @mswjs/interceptors 0.45.6)는 Node 에서 fetch 가 아니라 소켓 수준에서 가로챈다(lib/node/net-*.js).
  • 기본 전략 onUnhandledFrame: "warn" 은 경고 뒤 요청을 그대로 통과시킨다 — 실제 localhost:8000 에 연결한다.
  • 이 파일의 테스트들은 /builds/{run}/spec, /stages 등에 핸들러가 없어 매번 통과 요청을 만들고, 클라이언트가 그것을 0.5초·1초 뒤 재시도한다. 그 재시도가 다음 테스트 시작과 겹친다.
  • 통과된 실제 연결이 살아 있는 동안 같은 origin 으로 가는 다음 요청이 그 연결에 실려 MSW 를 거치지 않고 함께 실패한 것으로 본다.

마지막 단계는 확인하지 못했다. 로컬에서는 재현되지 않는다: 미처리 요청과 처리 요청을 시점을 바꿔 가며 1,500회 겹쳐 봤지만 처리 요청은 한 번도 실패하지 않았다. 로컬의 localhost 는 IPv4 하나로만 풀리고([{"address":"127.0.0.1","family":4}]) CI 는 두 주소를 시도한다는 차이가 있다.

변경

  • vitest.setup.ts: 핸들러가 없는 요청을 전처럼 경고한 뒤, 통과시키지 않고 MSW 안에서 네트워크 오류로 끝낸다 (onUnhandledFrame 콜백이 HttpResponse.error() 를 던진다). 앱이 보는 결과는 같다 — fetch 가 reject 되고 연결 실패로 읽힌다. 달라지는 것은 테스트가 실제 소켓을 열지 않는다는 점뿐이다.
  • __tests__/unhandledRequests.test.ts: 실제 HTTP 서버를 띄워 놓고 핸들러 없는 요청을 보내, 요청이 reject 되고 경고가 나오고 서버에는 아무것도 도착하지 않음을 확인한다.
  • CHANGELOG.

검증

  • 새 테스트는 고치기 전 설정에서 실패한다: promise resolved "Response { status: 200 … }" instead of rejecting — 요청이 실제 서버에 닿았다.
  • npx vitest run 전체 → Test Files 237 passed (237), Tests 2391 passed | 12 skipped (2408). (건너뛴 것은 계약 없이 돌린 drift 테스트다.) 미처리 요청이 연결 실패로 끝난다는 데 기대던 테스트는 그대로 통과한다.
  • npx tsc --noEmit, eslint 출력 없음.

알아 둘 것

🤖 Generated with Claude Code

…twork

MSW's default strategy warns about an unhandled request and then performs it,
so a test that lacks a handler opens a real connection to localhost. The
request trace of a failing tableDetailSnapshot run shows a handled request
failing with 'fetch failed' without MSW seeing it start, just after earlier
tests' unhandled requests. Warn as before, then answer with a network error.

Refs #741

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Eomdahyeon
Eomdahyeon merged commit 43a622f into main Oct 5, 2026
17 checks passed
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