배경
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· 테스트 목록 분리