최종 갱신 (KST)

← 일감 목록
T-089

우편 테스트 하나가 절반 확률로 실패한다 — UserManager 싱글턴 공유

진우 Closed 우선순위 보통 목표 261010 · 보관됨

배경

UserMailTest.접속_중인_유저에게_보내면_그_유저의_우편함으로_도착한다 (Server/WSGameServer.Tests/User/UserMailTest.cs:215)가 실행할 때마다 약 50% 확률로 실패한다. 코드를 바꾸지 않아도 결과가 갈리므로, 진짜 회귀가 섞여도 "또 그 테스트겠지" 하고 넘기게 된다.

T-092(인챈트) 작업 중 발견했다(2026-09-23). 인챈트 이전 커밋 4bd74be에서도 10회 중 5회 실패해, 인챈트가 만든 문제가 아니라 원래 있던 것이다.

원인 추정 (미확정)

이 테스트는 프로세스 전역 싱글턴 UserManager.Instance에 JoinUser/LeaveUser를 한다. xUnit은 테스트 클래스를 기본적으로 병렬 실행하고, 이 테스트 프로젝트에는 [Collection]·CollectionBehavior 설정이 없다. UserManagerTest 등 같은 싱글턴을 만지는 클래스와 동시에 돌면 서로의 유저를 보거나 지우는 것으로 보인다.

FakeLogicExecutor·UserManagerTest의 주석이 이미 "OnDestroy가 UserManager.Instance(전역)를 오염시킨다"고 경고하고 있다 — 같은 뿌리다.

단서 (2026-10-01, T-058) — 로그인 마무리(User.Login)가 UserManager.Instance.JoinUser를 부른다. LoginRepository.Apply()까지 도는 테스트가 uid 7로 로그인하고 내리지 않으면 같은 uid 7을 쓰는 이 테스트가 그 유저에게 우편을 보낸다. T-058의 재로그인 테스트가 그렇게 짜여 실패가 거의 매번으로 늘었다가, uid 분리 + LeaveUser로 원래 빈도로 돌아왔다. 남은 의심: CharacterAptitudeRepositoryTest.찍은_보너스는_저장되고_로그인_조회로_되읽힌다(uid 7 · 내리지 않음).

할 일

  • [x] 원인 — 전역 UserManager.Instance를 병렬 테스트가 공유했다(로그인 마무리가 uid 7을 올리고 내리지 않은 테스트가 있었다)
  • [x] 처리 방침 — 주입(2026-10-01). User는 매니저를 모른다: 등록·해제는 LoggedIn·Left 이벤트를 매니저가 듣고 하고, 다른 유저 조회(치트 우편 수신자 · 전체 우편 전달)는 좁은 IOnlineUsers로 받는다. 테스트는 TestUserBuilder.Online(테스트마다 새 목록)
  • [x] 전체 스위트 10회 연속 — 10/10 통과(732개)

완료 조건

전체 테스트를 10회 연속 돌려 이 테스트가 한 번도 실패하지 않는다.

막고 있는 것 / 선행 일감

  • 없음. 다만 T-020이 "UserManager.Instance 처리 방침을 먼저 고른다" 를 선행으로 두고 있다 — 같은 결정이다. 둘 중 먼저 착수하는 쪽이 방침을 정하고 다른 쪽에 적는다.

관련 커밋

  • 이 커밋 — IOnlineUsers · User.LoggedIn/Left · 테스트 목록 분리