상식닷컴
로그인
가입하기
2026년 상식닷컴 선정 식당 & 카페 리스트
2025년 2026년 신상 호텔 리스트
최근에 오픈한 호텔을 찾는다면 살펴보세요
일주일 식단표 어플
자동 일주일 식단표 어플
안드로이드
아이폰
주식 & 코인 차트의 신
1000만원으로 2000만원 만들기 프로젝트
궁금한 상식 보기
중장년일자리의 긍정적인 변화: 6가지 이유로 좋은 습관을 기르자!
80대할아버지선물로 지역 특산물을 찾아보는 것도 좋을까요?
80대할아버지선물로 선택한 계절별 특산물은?
여름이 오면 생각나는 콩국수, 5가지 이유
다이어리에 남길 만한 콩국수, 5가지 추천
독거노인CCTV 통신 방식은 무엇인가요?
어혈의 발생과 스트레스의 관계는 무엇인가요?
멜론의 아티스트 소통 방식은 어떤 형태인가요?
멜론에서 받은 '비밀번호 변경 메일'을 확인할 수 없는 경우 어떻게 하나요?
멜론에서 공연 소식은 어디서 확인할 수 있나요?
멜론에서 제공하는 인터뷰 콘텐츠는 어떤 형식인가요?
40대남자선물로 추천하는 뷰티 기기나 제품은?
Previous
Next
수정하기 - Robolectric을 사용하여 비동기 작업을 테스트하는 방법은 무엇인가요?
닉네임
비밀번호
제목
내용
[이미지 업로드는 권한이 있는 사람만 가능. 하단 카톡으로 연락]
Robolectric은 Android의 단위 테스트 라이브러리로, Android 프레임워크 코드를 JVM 상에서 실행할 수 있게 해줍니다. 하지만 실제 안드로이드 디바이스가 아닌 환경에서 비동기 작업(예: `Handler`, `<a href='https://sangseek.com/sangseeks/AsyncTask/ko'>AsyncTask</a>`, `<a href='/sangseeks/Thread/ko'>Thread</a>`, `ExecutorService`, RxJava, LiveData 등)을 테스트할 때는 동기화 문제나 타이밍 문제 때문에 테스트가 제대로 동작하지 않는 경우가 종종 있습니다. 이럴 때 Robolectric이 제공하는 메인 루퍼(MainLooper), 스케줄러를 활용해 비동기로 예약된 작업(예: 메시지, Runnable 등)을 강제로 실행시키거나 제어함으로써 테스트를 안정적으로 수행할 수 있습니다. 아래는 Robolectric을 이용하여 비동기 작업을 테스트하는 일반적인 방법을 정리한 상세 설명입니다. --- 1. Robolectric 테스트 환경에서 비동기 작업의 문제점 - Android 앱이 동작할 때 UI Thread(Main Thread)는 메시지 큐(Message Queue)를 통해 <a href='https://sangseek.com/sangseeks/콜백/ko'>콜백</a>이나 Runnable이 실행됨 - Robolectric은 안드로이드 프레임워크중 Looper와 MessageQueue를 JVM에서 흉내내지만, 실제 디바이스처럼 자동으로 메시지가 처리되지 않음 - 따라서 `Handler.post(Runnable)`, `AsyncTask.execute()`, `LiveData`나 RxJava의 비동기 작업 등은 별도의 제어 없이는 테스트 중에 실행되지 않을 수 있음 - 이런 문제로 인해 테스트가 실패하거나 무한 대기 상태가 발생할 수 있음 --- 2. 로보렉틱에서 비동기 작업 제어를 위한 주요 API - `ShadowLooper` : Robolectric이 만들어낸 `Looper`에 대한 제어용 클래스. 메시지 큐를 조작해 예약된 작업을 실행시키거나 진행시킬 수 있음. - `ShadowLooper.getMainLooper()` : 메인 스레드인 기본 Looper의 쉐도우 객체를 가져옴. - `ShadowLooper.runToEndOfTasks()` : 메시지 큐에 스케줄된 모든 작업을 즉시 실행 - `ShadowLooper.idleOneTask()` : 메시지 큐에 하나의 작업만 실행 - `Robolectric.flushForegroundThreadScheduler()` : 메인 스레드 작업 스케줄러를 비움(face로 모든 작업 실행) - `Robolectric.flushBackgroundThreadScheduler()` : 백그라운드 스레드 작업 스케줄러 작업 실행 - `Robolectric.pauseMainLooper()` 및 `Robolectric.unPauseMainLooper()` : 메인 루퍼를 멈췄다가 재개 가능 --- 3. 일반적인 비동기 작업 테스트 패턴 3-1. Handler 또는 Runnable 비동기 처리 테스트 ```java @Test public void testHandlerPostRunnable() { Handler handler = new Handler(Looper.getMainLooper()); AtomicBoolean executed = new AtomicBoolean(false); handler.post(() -> executed.set(true)); // 실제로 Runnable이 메인 메시지 큐에서 처리되도록 실행 ShadowLooper.runMainLooperOneTask(); // 또는 ShadowLooper.getShadowMainLooper().runToEndOfTasks(); assertTrue(executed.get()); } ``` - `Handler.post()`로 예약된 Runnable은 메시지 큐에 들어가지만 자동 실행되지 않음 - `ShadowLooper.getShadowMainLooper().runToEndOfTasks()`를 호출해서 즉시 실행시키면 테스트 코드가 해당 Runnable 동작을 검증할 수 있음 3-2. AsyncTask 테스트 ```java @Test public void testAsyncTask() { AtomicBoolean done = new AtomicBoolean(false); MyAsyncTask task = new MyAsyncTask(() -> done.set(true)); task.execute(); // AsyncTask는 내부적으로 serialExecutor, 백그라운드 스레드, 메인 스레드 동기 때문에 // Robolectric 스케줄러를 먼저 플러시해 비동기작업 완료 처리 해야 함 Robolectric.flushBackgroundThreadScheduler(); Robolectric.flushForegroundThreadScheduler(); assertTrue(done.get()); } ``` - AsyncTask 내부는 백그라운드 작업 + 메인 스레드 후처리 순으로 동작함 - `flushBackgroundThreadScheduler()`와 `flushForegroundThreadScheduler()`를 호출해서 각각의 스케줄러 작업을 강제로 실행시킴 - 그렇지 않으면 작업이 백그라운드에서 처리되기 전에 검사하게 되어 테스트 실패함 3-3. LiveData 또는 HandlerThread 등 테스트 ```java @Test public void testLiveDataUpdate() { MutableLiveData<String> liveData = new MutableLiveData<>(); // Observer 등록 liveData.observeForever(value -> assertEquals("newValue", value)); // LiveData는 내부적으로 메인 루퍼 스케줄러 통해 값 전달되므로 liveData.postValue("newValue"); // 스케줄러 플러시 ShadowLooper.runMainLooperOneTask(); } ``` - LiveData는 postValue()를 호출하면 메인 스레드 메시지 큐에 전달 예약됨 - 따라서 메시지 큐에 있는 작업을 명시적으로 실행시켜야 observer가 데이터 변경을 정상 수신함 --- 4. RxJava, Coroutine 등과 결합한 비동기 테스트 시 주의점 - RxJava의 경우 Schedulers를 `Schedulers.trampoline()`으로 교체해서 동기 실행하게 변경하거나, 테스트 전용 Scheduler를 Injector 또는 RxJavaPlugins를 통해 설정 - Kotlin Coroutine은 Main Dispatcher를 `Dispatchers.Unconfined` 혹은 Robolectric Test에 맞춰 `Dispatchers.setMain` <a href='https://sangseek.com/sangseeks/Mockito/ko'>Mockito</a> 등의 룰 등을 써서 변경 후 테스트가 일반적 --- 5. 요약 및 팁 - Robolectric은 안드로이드 메시지 큐와 루퍼를 흉내내지만, 비동기 작업이 자동으로 실행되지 않아 명시적으로 스케줄러를 flush하거나 메시지큐를 실행시켜줘야 함 - `ShadowLooper.getShadowMainLooper()` 를 이용해 메시지 큐에 쌓인 동기 작업(Runnable, 메시지 등)을 즉시 실행 가능 - `Robolectric.flushForegroundThreadScheduler()` / `flushBackgroundThreadScheduler()`는 AsyncTask 등 작업 스케줄러를 진행하는 데 유용 - LiveData나 Handler 등의 비동기 콜백은 처리될 때까지 메시지 큐를 도는 로직을 넣어줘야 안정적인 테스트가 가능 - RxJava나 Coroutine 뷰 측면 테스트에서는 별도의 테스트 Scheduler 또는 Dispatcher 교체가 필요하므로 Robolectric과 별개로 핸들링 필요 --- 이처럼 Robolectric을 활용해서 비동기 코드를 테스트 할 때는 테스트 내에서 동기화 지점을 명확히 하여, '언제 비동기 작업이 완료되었는지'를 제어하는 것이 중요합니다. 이를 위해 위에서 설명한 `ShadowLooper` 와 `flushScheduler` API 등을 적극 활용하면 안정적이고 재현 가능한 단위테스트가 가능합니다.
이용안내
커뮤니티 이용안내
×
- 게시한 게시글로 발생하는 문제는 게시자에게 책임이 있습니다.
- 게시글이 타인/타업체의 저작권을 침해할 경우 모든 책임은 게시자에게 있습니다. 게시자가 모든 손해를 부담해야 합니다.
- 상식닷컴 운영자는 게시자와 상의하지 않고 게시글을 수정 또는 삭제할 수 있습니다.
- 상식닷컴 운영자는 깨끗한 커뮤니티 공간을 만드는 것이 1순위입니다.
수정하기
취소하기