Mock API แบบง่ายๆ โดยไม่ง้อ Backend ด้วย Charles

Dew
Black Lens
Published in
4 min readFeb 7, 2017
ศาสตราจารย์ Charles Xavier กำลังใช้พลังจิตอ่านความคิด เหมือนที่ Charles เจาะเข้าไปดู traffic (ภาพประกอบจากภาพยนต์เรื่อง X-men: First Class)

Prelude

เคยไหมที่ต้องทำแอปในขณะที่ API ยังไม่มีให้ใช้ ?
(รีบปั่น prototype ไปโชว์ VC)

เคยไหมที่ต้อง hardcode mock data จนทำให้ code หลักเปรอะเปื้อน ?
(ไม่ clean เอาซะเลย)

ดีขึ้นมาหน่อย… เคยไหมที่ต้องมาทำ gradle build variant เพื่อสลับระหว่าง real กับ mock repository ?
(อันนี้พอได้ แต่สุดท้ายงานแอบเยอะไปนะ)

เคยไหมที่ API ส่งข้อมูลลงมาไม่ครบทุก case ที่อยาก test ?
🙃

และเคยไหมที่ทีม Backend งานล้นมือจนไม่ว่างมา support สักกะที ?
(งานเยอะแต่คนไม่พออีกแว้ว 😵 )

วันนี้ปัญหาทั้งหมดจะหมดไป เราขอแนะนำให้ท่านได้รู้จักกับ Charles …. (ทำเสียง echo)

Say hello to Charles

Charles คือ tool ที่ทำให้เราสามารถ monitor HTTP traffic ได้ ลองนึกภาพว่าเราสามารถมองเห็นข้อมูลที่ออกมาจากแอปของเราทั้งฝั่ง request และ response แถมยังสามารถทำตัวเป็น Man-in-the-middleใส่ breakpoint เพื่อแก้ไขข้อมูลก่อนจะส่งต่อได้

Charles ยังสามารถ redirect request ไปยัง endpoint อื่นหรือจะให้ทำตัวเหมือน Web Server ตอบ response เองด้วย mock data ที่เราเตรียมไว้ก็ย่อมได้ ในบทความนี้เราจะมาแนะนำการ debug และการ mock data ด้วย Charles แต่ก่อนอื่นมาดูกันว่าเราจะต้องเตรียมอะไรกันก่อนบ้าง

Setup Proxy/Phone/Recording

อันดับแรกเลยคือไปโหลด Charles มาครับ โดยตัวที่ผมใช้ในบทความนี้เป็นตัว trial เวอร์ชัน 4.0.2 สำหรับ macOS ใช้ได้ 30 วันและเปิดแต่ละครั้งได้แค่ 30 นาที ถ้าถูกใจก็จัด license เลยจ้ะ

หลังจากติดตั้งเสร็จแล้วเราก็มาเริ่มกันเลย เมื่อเราเปิด Charles เข้ามาก็จะพบว่ามัน monitor traffic จากคอมเราอยู่แล้ว เดี๋ยวตรงนี้เพื่อไม่ให้เราสับสนระหว่างอันไหนเป็น traffic จากเครื่องแมค อันไหนมาจากโทรศัพท์เราก็ไปที่เมนู Proxy แล้วติ้กเมนู macOS Proxy ออกครับ

ก่อนจะเริ่มดัก traffic จากโทรศัพท์ เราต้องให้โทรศัพท์กับคอมของเราอยู่ใน network เดียวกันก่อนนะครับ ซึ่งปกติถ้าต่อ wifi อันเดียวกันก็โอเคแล้ว จากนั้นเราก็มาตั้งค่า proxy ในโทรศัพท์กัน ในบทความนี้ผมใช้ Android นะครับ

เริ่มต้นจากหา ip address ใน network ของเครื่องแมค หรือจะดูผ่าน Charles ตรงเมนู Help -> Local IP Address ก็ได้ จากนั้นก็ไปดูหมายเลข port ของ proxyโดยไปที่เมนู Proxy -> Proxy Settings… เราก็จะเห็น port ที่ Charles เปิดรออยู่ ตรงนี้จะเปลี่ยนเป็นอย่างอื่นก็ได้ครับเผื่อใครมีเลขนำโชค

จากนั้นก็ตั้งค่า Proxy settings ของโทรศัพท์ครับ ซึ่ง android แต่ละรุ่นอาจจะเข้าไปไม่เหมือนกัน โดยปกติจะอยู่ตรง wifi settings

เมื่อตั้งค่าบนโทรศัพท์เรียบร้อย Charlese บนแมคก็จะมีหน้าต่างเด้งขึ้นมาบอกว่ามี connection เข้ามาจะอนุญาตให้ผ่าน Charles ไหม ตรงนี้ก็ตอบ Allow ไป

ตอนนี้เราก็จะเริ่มเห็น traffic ที่มาจากโทรศัพท์แล้ว ลองเปิดแอปในโทรศัพท์เล่นดู แล้วสังเกตผลใน Charles

Debugging

เมื่อทุกอย่างพร้อมแล้วเรามาลอง debug กันเลย ในตัวอย่างนี้ผมจะลองทดสอบ Charles กับโปรเจค StarWars-Architecture ที่นายTravis P Suban ทำไว้ซึ่งใช้ Star Wars API และเพื่อให้ debug ได้สะดวกขึ้นเราจะทำการ filter ให้ Charles ดักเฉพาะข้อมูลที่ยิงไปหา Star Wars API เท่านั้น ไม่งั้น Charles จะแสดง traffic ทั้งจาก Star Wars API ปนกับ traffic อื่นๆ ที่แอปอื่นอาจกำลังเรียก โดยเราจะไปปรับที่เมนู Proxy -> Recording Settings... จากนั้นเลือก include และใส่ url ของ Star Wars API เข้าไปแบบนี้

ตอนนี้ Charles ก็จะดักแค่ traffic ของ Star Wars API พอลองเข้าแอป Star Wars Architecture จะเห็นว่ามีการยิงไปที่ api/films พอคลิกเข้าไปดูรายละเอียดของหนังภาค The Force Awaken ก็จะเห็นว่ามีการยิงไปที่ api/films/7

คราวนี้เราจะมาลอง debug api ของหน้า movie details กัน คลิกขวาที่ api/films/7 แล้วเลือก breakpoint

ลองเข้าหน้า movie details ของ The Force Awaken อีกรอบคราวนี้จะเห็นว่า Charles ดัก request ไว้ ตรงจุดนี้เราสามารถเข้าไปแก้ข้อมูลใน request ได้ แต่ตอนนี้ผมจะลองปล่อยไปก่อนโดยการกดที่ปุ่ม execute แล้วรอ response จาก API แปปนึง Charles ก็จะมาหยุดที่ response อีกครั้ง คราวนี้ลองแก้ข้อมูลดูหน่อย

เปลี่ยนชื่อภาคเป็น Return of the Black Lens !

จะเห็นว่าคราวนี้แอปเราแสดงชื่อหนังเปลี่ยนไปตามที่เราแก้ด้วย Charles เรียบร้อย

ความสามารถในการ debug ของ Charles มีประโยชน์หลายอย่าง เช่นเราสามารถดูได้ว่าเราส่ง request/response หน้าตาแบบไหน หรือเราอยากจะลองเปลี่ยนค่า field บางตัวที่ API ส่งกลับมาเพื่อดูว่าแอปเราจะตอบสนองยังไง

ต่อไปเราจะมาลองเปลี่ยน Charles ให้ทำหน้าที่ mock server กัน

Map local

Map Local เป็นฟีเจอร์ที่ผมชอบเป็นการส่วนตัว ฟีเจอร์นี้ Charles จะทำหน้าที่คล้ายๆ กับ Web Server คือเราสามารถให้ Charles ตอบ response ด้วย mock data ที่เราเตรียมไว้ในเครื่องแมคเมื่อมี request ไปยัง API ที่เรากำหนดไว้ได้เลย

ประโยชน์ของฟีเจอร์นี้คือในกรณีที่เราอยากจะทดสอบแอปโดยไม่อยากรอให้แอปต้องโหลด API ตลอดเวลาพอใช้ Map Local แอปก็จะโหลดข้อมูลได้แทบจะทันทีเพราะอยู่ใน network เดียวกัน หรือในกรณีที่ API ยังไม่มีให้ใช้ เราก็สามารถใช้ Map Local กับ mock data ที่เราเตรียมไว้ได้ หรืออีกกรณีคือการทำ UI Test เช่น Espresso เราสามารถใช้ Map Local ตอนรัน Epresso Test Case เพื่อจำกัดตัวแปรทางด้าน network เวลาทดสอบ UI ออกไปได้

พล่ามมาเยอะ มาลองกันเลยดีกว่า ก่อนอื่นผมได้เตรียม JSON ไว้ประมาณนี้

{
"title": "Return of the Black Lens !",
"episode_id": 7,
"opening_crawl": "He is back ! Who ?!?",
"director": "Travis P Suban",
"producer": "Johnny Dew",
"release_date": "2017-02-31"
}

จากนั้นเราก็เลือกว่า API ไหนที่เราจะทำการ Map Local โดยที่ผมคลิกขวาที่ api/films/7 จากนั้นเลือก Map Local...

ผมใส่ path เป็น api/films/* เพื่อจะ map ทุก path ที่วิ่งไปที่ movie details และเลือก Local path เป็นไฟล์ JSON ที่เราเตรียมไว้

เมื่อทุกอย่างเรียบร้อยแล้ว เรามาลองเปิดแอปกัน จะเห็นว่าหน้าแอปเราแสดงข้อมูลที่มาจาก JSON ที่เราเตรียมไว้ และสังเกตุเห็นอีกอย่างว่าข้อมูลในแอปวิ่งมาแทบจะทันทีโดยไม่ต้องรอโหลดเลย

เมื่อเราคุม response data ไว้แล้วเราสามารถแก้ JSON แล้วกด refresh ในแอปเพื่อให้โหลดข้อมูลใหม่ได้เลย สะดวกมากๆ

ส่งท้าย

นอกจากความสามารถในการ debug และ map local ที่กล่าวมา Charles ยังมีความสามารถอีกหลายอย่างที่เป็นประโยชน์และช่วยทำให้ชีวิตเดฟง่ายขึ้นเช่น

  • Map Remote ใช้ redirect request ไป endpoint อื่น
  • Throttle ใช้จำลองสถานการณ์เนทช้าาาา
  • And more …

ลองเล่นแล้วถ้าชอบก็อย่าลืมอุดหนุน license ของเขาด้วยนะครับ

--

--