เมื่อ Token ตัวร้ายหมดอายุ ตอนที่ 2 (Refresh Token in Android with Retrofit Part 2)

Taweewong Tocharoen
Nextzy
Published in
2 min readMar 4, 2020

--

ถึงแม้เราจะได้ผ่านพ้นช่วงเวลาในการ implement มาแล้ว แต่งานของเรานั้นยังไม่หมดเพราะว่าในตอนนี้เราจะมาเขียน Test ให้กับเจ้า Interceptor กันต่อ

ส่วนใครยังไม่ได้อ่านตอนแรกกลับไปอ่านได้ที่นี่ครับ

Setup

เอาล่ะ มาเตรียมวัตถุดิบในการ Test กันก่อน โดยสิ่งที่เราจะใช้ก็คือ

  1. Mockito
  2. OkHttp Mock Web Server
  3. Retrofit Mock
  4. Gson
testImplementation 'org.mockito:mockito-core:3.2.4'
testImplementation 'com.squareup.okhttp3:mockwebserver:4.2.2'
testImplementation 'com.squareup.retrofit2:retrofit-mock:2.6.2'
implementation 'com.squareup.retrofit2:converter-gson:2.6.2'

It’s Test time!

1. Mock Refresh Token Service

อย่างที่รู้กันว่าภายใน Interceptor ของเราจะต้องมีการยิง Refresh Token ด้วย เราจึงต้องสร้าง Mock ของ Refresh Token Service ขึ้นมาเตรียมเอาไว้ก่อนเพื่อรอวันที่จะใส่เข้าไปใน Interceptor อาจจะใส่เข้าไปผ่านทาง Constructor หรือจะ Inject เข้าไปก็ตามสะดวกเลย แต่ตอนนี้เรามา mock กันก่อนนะครับ

val refreshTokenService = mock(RefreshTokenService::class.java)

พอเราสร้างตัว mock แล้วเราก็กำหนดให้มัน return response ของ refresh token ออกมาแบบนี้ครับ

`when`(refreshTokenService.refreshToken()).thenReturn(Calls.response(RefreshTokenResponse()))

จะเห็นว่าผมให้มัน return เป็น Calls ซึ่งโดยปกติแล้วเวลาเราเรียก service โดยใช้ Retrofit มันจะ return Call เพื่อรอวันที่จะโดนเรียก enqueue หรือ execute แล้วรับค่าจาก service จริงๆ แต่ว่า Calls เนี่ยมันคือตัว mock ของ Call ครับ อยู่ใน Retrofit Mock ที่เราใส่มานั่นแหละ มันต่างจาก Call ตรงที่เราสามารถกำหนดได้เองเลยว่าตอนที่มันถูกเรียก enqueue หรือ execute แล้วจะให้ค่าที่ได้กลับมาเป็นอะไร

2. Create Mock Web Server

TLDR;
สำหรับคนที่ยังไม่รู้จัก Mock Web Server นะครับ มันก็คือการที่เราสร้าง Web Server จำลองขึ้นมา เราสามารถกำหนด URL ให้มันได้ กำหนดได้ว่าตอนที่เราเรียก service จะให้ return อะไรกลับไป และที่สำคัญก็คือเราสามารถกำหนดได้เลยว่าจะให้มันผ่าน Interceptor อะไรบ้างในสร้างเรียก service จำลองนี้ นี่ล่ะเหตุผลที่เราจะใช้เจ้านี่ในการ Test

แน่นอนว่าเราต้องเริ่มจากสร้าง object MockWebServer ขึ้นมา แล้วจากนั้นก็กำหนดว่า server จะ return อะไรให้บ้างโดยใช้คำสั่ง enqueue() หากเราใส่ enqueue หลายครั้ง server จะ return ค่าตามลำดับที่ถูกเรียก เช่น เรียก server ครั้งแรกจะ return ค่าของ enqueue อันแรก พอเรียกอีกก็จะไล่ตามลำดับ

จาก code จะกำหนดให้การเรียก server ครั้งแรก return เป็น 401 Token Expired จากนั้นเมื่อถูกเรียกอีกครั้งถึงจะ return ค่าที่ success จริงๆ เพราะเราต้องการให้ flow เป็นแบบนี้

call server (1st) return 401Interceptor do refresh tokenInterceptor call server againcall server (2nd)return 200

3. Create OkHttpClient and Request

เราได้ mock ฝั่ง server กันไปแล้วต่อไปเราจะสร้างฝั่ง client เพื่อจะเอาไว้เรียก server กันบ้าง

คราวนี้ถึงเวลาที่ Interceptor ของเราจะออกโรงแล้ว ผมสร้าง TokenExpiredInterceptor พร้อมกับใส่ refreshTokenService ที่เรา mock เอาไว้ แล้วใส่ interceptor เข้าไปใน client ของเรา

พอเราสร้าง client แล้วเราก็สร้าง request แล้วยัดเข้าไปใน client อีกที

เท่านี้ client ของเราก็พร้อมเรียก mock server ของเราแล้ว

4. Call the Mock Server and Verify Result

ต่อจากข้างบนเลยนะครับ เราได้สร้าง call จาก OkHttpClient กันไว้แล้ว เราก็สั่ง execute() ได้เลย! แล้วก็เอาผลลัพท์ที่ได้มา assert ตามสะดวกเนอะ จากนั้น shutdown server แล้วก็พนมมือขึ้นมาบูชาสิ่งศักดิ์สิทธิ์ขอให้ผ่านไปได้ด้วยดี สาธุ~ เท่านี้ก็เป็นอันเรียบร้อยแล้วครับ

แอบใส่ verify ซะหน่อย จะได้รู้ว่ามันเรียก refreshToken() จริงๆ

ผลลัพท์การ test จะเป็นประมาณนี้นะครับ จะเห็นว่าเราจะได้ response สองครั้ง ครั้งแรกเป็น 401 แล้วครั้งที่สองเป็น 200 ตามที่เราต้องการ

และนี่ก็เป็น code ทั้งหมดครับ

Conclusion

ในการ test Interceptor นั้นเราจะใช้ Mock Web Server ช่วย เพื่อที่เราจะได้เลือกทดสอบ Interceptor ของเราได้ แล้วเราก็สามารถวาง flow ของการ test ได้ด้วย เช่น ให้ส่ง Request อะไรไป ผ่าน Interceptor อะไรบ้าง แล้วได้ Response อะไรกลับมา แล้วใช้ Mockito ช่วย mock ของอื่นๆ เพิ่มเติม

ก็จบกันไปอีกบทความนะครับสำหรับการ test Interceptor ด้วย Mock Web Server แต่ว่ามันเอาไปประยุกต์ใช้ประโยช์ได้หลายอย่างนะครับ เราอาจจะเขียน Interceptor ที่แก้ไข request ข้างในก่อนส่งไปยัง server ตอน test เราก็สามารถดึง request ที่แก้แล้วออกมาดูอะไรอะไรแบบนี้

ขอพระเจ้าอวยพรให้กับการเขียน Test ของคุณ แล้วไว้เจอกันใหม่ครับ

--

--