대부분 restful API를 사용하는 안드로이드 네이티브 개발자들이라면
Retrofit을 쉽게 사용할것이다.
구현 자체는 어렵지 않으나… API 개발은 프로젝트에서 독립적인 영역이고,
때문에 시간이 지남에 따라 API의 변경이라든지, 구조의 변경..뭐 이런게 있을 수 있다.
변경 정도면 양반이고….API가 없는 상태에서 개발을 시작하게 되는 경우도 드물지 않다……
이 말은 즉슨, mock test가 필수적이라는것
MockWebServer
전제 조건
- Retrofit 기반이므로 미리 준비되어 있어야 한다
- req /response 객체 있어야 한다
- 단위 테스트의 기본을 이해해야 한다
구현 방법
- dependency 추가
testImplementation ("com.squareup.okhttp3:mockwebserver: 4.11 . 0 ")
- API interface 준비
interface FeedbackApi {
@GET("feedback/user/get/?")
suspend fun getFeedbackQuestions(
@Query("uid") userId: String,
@Query("fid") featureId: String
): FeedbackQuesDTO
}
- API에 해당하는 테스트 클래스 만들기
- tip ; 이 인터페이스를 클래스로 변경한 다음 ALT+INSERT -> 테스트 -> 테스트 클래스 생성을 누른 다음 다시 인터페이스로 되돌리면 됨
- 테스트 클래스에 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)
}
}
- memory leak 을 방지하기 위해 서버 종료도 잊지말기
@AfterEach
fun afterEach () {
server.shutdown()
}
- 테스트 코드 예시
@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) //호출 응답으로 얻는 데이터는 동일해야함
. }
- 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 ) //호출 응답으로 얻는 데이터는 동일해야함
}
- 응답코드 설정해서 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