Retrofit API Test

2024. 1. 3. 10:55개발/Android

대부분 restful API를 사용하는 안드로이드 네이티브 개발자들이라면

Retrofit을 쉽게 사용할것이다.

구현 자체는 어렵지 않으나… API 개발은 프로젝트에서 독립적인 영역이고,

때문에 시간이 지남에 따라 API의 변경이라든지, 구조의 변경..뭐 이런게 있을 수 있다.

변경 정도면 양반이고….API가 없는 상태에서 개발을 시작하게 되는 경우도 드물지 않다……

이 말은 즉슨, mock test가 필수적이라는것

MockWebServer

전제 조건

  1. Retrofit 기반이므로 미리 준비되어 있어야 한다
  1. req /response 객체 있어야 한다
  1. 단위 테스트의 기본을 이해해야 한다

구현 방법

  1. dependency 추가
testImplementation ("com.squareup.okhttp3:mockwebserver: 4.11 . 0 ")
  1. API interface 준비
interface FeedbackApi {

    @GET("feedback/user/get/?")
    suspend fun getFeedbackQuestions(
        @Query("uid") userId: String,
        @Query("fid") featureId: String
    ): FeedbackQuesDTO
}
  1. API에 해당하는 테스트 클래스 만들기
    1. tip ; 이 인터페이스를 클래스로 변경한 다음 ALT+INSERT -> 테스트 -> 테스트 클래스 생성을 누른 다음 다시 인터페이스로 되돌리면 됨
  1. 테스트 클래스에 mock server의 인스턴스, 인터페이스 준비
class  FeedbackApiTest { 
    private  lateinit  var server: MockWebServer 
    private  lateinit  var api: FeedbackApi 

    @BeforeEach //JUnit5 사용 
    fun  beforeEach () { 
        server = MockWebServer() 
        api = Retrofit.Builder() 
            .baseUrl(server. url( "/" )) //이와 같은 기본 URL을 전달
             . .addConverterFactory(GsonConverterFactory.create()) 
            .build().create(FeedbackApi:: class .java) 
    } 
}
  1. memory leak 을 방지하기 위해 서버 종료도 잊지말기
@AfterEach 
    fun  afterEach () { 
        server.shutdown() 
    }
  1. 테스트 코드 예시
@Test 
    fun `getFeedbackQuestions, presents Success` () = runTest { 
        val dto = FeedbackQuesDTO() //응답으로 돌려주고 싶은 객체 
        private  val gson: Gson = GsonBuilder().create() 
        val json = gson.toJson(dto )!! //GSON을 사용하여 객체를 json 문자열로 변환 
        val res = MockResponse() //서버 호출
         res.setBody(json) //fake response의 body를 json string으로 변환
         server.enqueue(res) //서버 응답 큐에 추가 

        val  data = api.getFeedbackQuestions( "" , "" ) // fake call
         server.takeRequest () //서버가 요청을 받도록

         .assertEquals( data , dto) //호출 응답으로 얻는 데이터는 동일해야함
     . }
  1. wrapper사용하는 경우
@Test 
    fun `getFeedbackQuestions, presents Success` () = runTest { 
        val res = MockResponse() //서버 호출에 대한 가짜 응답 만들기
         res.setBody( "[]" ) // 응답으로 예상되는 json 문자열
         server.enqueue(res) //서버 응답 큐에 추가 

        val  data = api.getFeedbackQuestions( "" , "" ) //가짜 서버를 호출
         server.takeRequest() //서버가 요청을 받도록

         AssertEquals( data .body()!!.isEmpty(), true ) //호출 응답으로 얻는 데이터는 동일해야함
     }
  1. 응답코드 설정해서 test하는 경우
fun `getFeedbackQuestions, returns Error`() = runTest {
        //서버가 응답을 받을 수 있도록 준비
        val res = MockResponse()
        res.setResponseCode(404)
        server.enqueue(res)

        //호출 생성
        val repo = FeedbackRepoImpl(api, mockk())
        val data = repo.getFeedbackQuestions("", "")

        //서버에 생성된 호출을 수락하도록 지시
        server.takeRequest()

        assert(data is MyResponseState.Error)//응답코드 400이므로 RepoImpl을 사용하여 MyResponseState.Error를 보냄
    }

Uploaded by N2T

'개발 > Android' 카테고리의 다른 글

메모리 누수를 해결하는 조금 더 자세한 방법  (2) 2024.01.03
Android SSL Pinning  (0) 2023.12.15
Android의 모듈식 접근 방식  (0) 2023.12.15
MenuProvider  (0) 2023.12.15
메모리 누수의 원인 10가지  (0) 2023.12.15