시배's Android

Hi Jack Mocker | 개선기 (1) feat.UninitializedPropertyAccessException 본문

Android/Hi Jack Mocker

Hi Jack Mocker | 개선기 (1) feat.UninitializedPropertyAccessException

si8ae 2024. 7. 12. 17:47

Hi Jack Mocker란?

 

GitHub - koreatlwls/Hi-Jack-Mocker: Hi-Jack-Mocker is a project that leverages OkHttp3's interceptor to intercept and modify net

Hi-Jack-Mocker is a project that leverages OkHttp3's interceptor to intercept and modify network requests and responses, allowing you to verify the UI easily. - koreatlwls/Hi-Jack-Mocker

github.com

 

Hi Jack Mocker는 비개발자도 UI 엣지 케이스를 쉽게 테스트할 수 있도록 돕는 라이브러리입니다. 이 프로젝트는 OkHttp3 인터셉터를 활용하여 네트워크 요청과 응답을 가로채고 수정할 수 있게 합니다. 이를 통해 개발자뿐만 아니라 다양한 사용자들이 다양한 시나리오를 테스트할 수 있게 합니다.

 

HiJackMocker 라이브러리 0.1.0 버전 배포 및 UninitializedPropertyAccessException 문제 해결

HiJackMocker 라이브러리의 버전 0.1.0Maven Central에 배포한 후, 실제 프로젝트에서 UninitializedPropertyAccessException 오류를 해결한 방법에 대해 설명하겠습니다.

HiJackMocker 0.1.0 버전 Maven Central에 배포하기

먼저, HiJackMocker의 버전 0.1.0을 Maven Central에 성공적으로 배포했습니다. 이 버전부터는 Maven Central에서 HiJackMocker를 손쉽게 의존성으로 추가할 수 있습니다.

debugImplementation("io.github.koreatlwls:hjm:0.1.3")

이제 HiJackMocker를 Maven Central에서 직접 다운로드하고 사용할 수 있게 되었습니다.

실제 프로젝트에서 발생한 UninitializedPropertyAccessException

라이브러리를 적용한 실제 프로젝트에서 UninitializedPropertyAccessException 오류가 발생했습니다. 오류 메시지는 다음과 같습니다

UninitializedPropertyAccessException: lateinit property hjmInterceptor has not been initialized

이 오류는 HiJackMocker에서 HjmInterceptor가 lateinit으로 선언되어 있지만 초기화되지 않은 상태에서 사용되었기 때문에 발생했습니다.

문제의 원인

@Provides
@Singleton
fun provideHttpClient(): OkHttpClient =
    OkHttpClient.Builder()
        .readTimeout(TEN_SECONDS, TimeUnit.SECONDS)
        .connectTimeout(TEN_SECONDS, TimeUnit.SECONDS)
        .writeTimeout(TEN_SECONDS, TimeUnit.SECONDS)
        .addHiJackMocker()
        .addInterceptor(getLoggingInterceptor())
        .build()

일반적으로 Hilt를 사용하여 OkHttpClient 객체를 생성하여 주입받는 방식을 사용하는데, 이때 addHiJackMocker() 함수를 통해 interceptor를 추가하고 있습니다.
하지만 Hilt는 Compile타임에 의존성 객체를 생성하기때문에 HjmInterceptor가 initialize되지 않아 Exception이 발생하였습니다.

문제 해결 방법

문제를 해결하기 위해 addHiJackMocker 함수에서 HjmInterceptor초기화된 상태에서만 intercept 메소드를 호출하도록 수정했습니다. 초기화되지 않았을 경우에는 기본적인 OkHttp 요청을 그대로 진행하도록 변경했습니다.

 

변경 전 코드 : 

fun OkHttpClient.Builder.addHiJackMocker(): OkHttpClient.Builder =
    this.addInterceptor(hjmInterceptor)

변경 후 코드 : 

fun OkHttpClient.Builder.addHiJackMocker(): OkHttpClient.Builder =
    this.addInterceptor(
        Interceptor { chain ->
            if (this@HiJackMocker::hjmInterceptor.isInitialized) {
                hjmInterceptor.intercept(chain)
            } else {
                chain.proceed(chain.request())
            }
        }
    )

위의 코드에서는 HjmInterceptor초기화된 상태에서만 intercept 메소드를 호출하고, 초기화되지 않았을 경우에는 chain.proceed(chain.request())를 호출하여 기존의 OkHttp 응답을 그대로 반환하도록 구현했습니다.

Okhttp에 HiJackMocker 적용하기

Hilt를 사용하여 OkHttpClient를 설정할 때 HiJackMocker를 적용하는 예제를 보여줍니다.

@Provides
@Singleton
fun provideHttpClient(): OkHttpClient =
    OkHttpClient.Builder()
        .readTimeout(TEN_SECONDS, TimeUnit.SECONDS)
        .connectTimeout(TEN_SECONDS, TimeUnit.SECONDS)
        .writeTimeout(TEN_SECONDS, TimeUnit.SECONDS)
        .addHiJackMocker() // HiJackMocker를 추가합니다.
        .addInterceptor(getLoggingInterceptor()) // 다른 인터셉터를 추가합니다.
        .build()

이제 addHiJackMocker()를 통해 HiJackMocker의 HjmInterceptor를 OkHttpClient에 추가할 수 있으며, initialize 함수를 통해 HiJackMocker를 설정해두면 HjmInterceptor가 정상적으로 동작합니다.