[Golang] หลักการเขียน Unit test และ การ Mockup สำหรับ Http Client พร้อมตัวอย่าง

PanachaiNY
3 min readMar 30, 2022

--

Intro

โดยปกติแล้ว เวลาเราจะเขียนเทสที่ตัว service เราจะต้องทำการ mock dependency ซึ่งในที่นี้ก็คือ http client ใช่ไหมครับ ซึ่ง วิธีการทั่วไปเราจะทำการ Wrap http client ของเรา เช่น `net/http`, `resty` พอ Wrap เสร็จเราก็จะทำการเขียน Interface เพื่อทำการ mock ทั้ง class เพื่อเรียกใช้ในตอนเทส Service ครับ

Service แบบปกติ
Service แบบ Wrap client เรียบร้อย
เวลาเขียนเทส Service ในท่า ClientWrapper

แล้วเราจะทำการ เทส Wrap http client ของเรายังไง?

อย่างเช่น ถ้าเราอยากจะรู้ว่า map request / response ดัก Error ถูกต้องรึเปล่า

วันนี้มี Solution มานำเสนอครับ

[Solution 1] Mock External Service

solution นี้เป็นท่าที่ผมใช้มาตลอดคือการ Mock external service แล้วยิงหาโดยการเปลี่ยน Base url ไปเลย

โดยการใช้ APIB (API Blueprint) หรือ Mockoon

จริงๆ แล้วท่านี้เหมาะสำหรับการทำ Integration test มากกว่า ไม่ใช่ Unit test (เพราะถ้า mock ตาม scenario นี้ถึงตายแน่ๆ)

Normal
Mock way

Pros

  • เวลาเรา Dev สามารถใช้ตัว Mock API ในการ Dev ได้เลย ไม่จำเป็นต้องรอให้ฝั่งปลายทางทำเสร็จ หรือ แม้ปลายทาง Server down เราก็ทำงานได้ปกติไม่มีปัญหา
  • ไม่ต้องลงลึกการ Mock ในแต่ละภาษา จะดีในกรณีที่คุณใช้หลาย Stack แล้วไม่อยากจดจำการ Mock ในแต่ละภาษา
  • ไม่ต้องเสียเวลา Mock ตอนเทส และตอน Dev ทำครั้งเดียวจบ ใช้ด้วยกันได้เลย

Cons

  • มันช้าครับ เวลาเราจะรันเทส หรือ CI เราต้องรัน service mock ขึ้นมาด้วย
  • ใช้เวลาเขียนมากกว่าการ Mock ใน Code เพราะต้องเขียน Mock API ด้วย และตาม scenario อีก
  • maintain เหนื่อยใช้ได้ แม้ว่าจะทำที่เดียวแล้วจบใช้ได้ทั้งสอง แต่การ Mock ตาม scenario ขึ้นมาเป็น Mock API ก็ใช้ effort เยอะกว่า mock ใน unit test ครับ

[Solution 2] Mock in Unit test

เราจะทำการเขียนโดย Mock ใน unit test ไปเลย

Pros

  • เขียนง่าย ทำงานไว เหมาะกับ Unit test จัดๆ
  • ไม่ต้องรัน service mock ทำให้ Setup CI ได้ง่าย
  • Maintain ในระดับกลางๆ แม้ว่าจะต้องทำ Mock 2 ส่วนแยกกัน แต่โดยปกติ API Mock เราจะเขียนแค่ 1–2 case เช่น success / error แต่ในขณะที่ตัว Mock Unit test เราจะเขียนครบทุก scenario มี 20 ก็เขียน 20

Cons

  • ต้องศึกษา และหา tool ในการทำที่เหมาะกับแต่ละภาษา
  • ต้อง mock สองครั้งแยกระหว่าง API Mock สำหรับ Develop กับ Mock สำหรับ Unit test

ภาคปฏิบัติของ [Solution 2] Mock in Unit test

ตัวอย่าง client.go

จะทำการ Mock ได้ดังนี้

บรรทัด 5: ทำการประกาศ clientMock

บรรทัด 8: apply client เข้า `httpmock` (แนะนำใช้ใน Before all)

บรรทัด 11: reset mock (แนะนำใช้ใน Before each)

บรรทัด 13–20: ทำการ mock response และ บันทึกลง httpmock เพื่อรอรับ request

บรรทัด: 22–25: ทำการ call http แบบปกติ

บรรทัด 29: ทำการ remove httpmock ออก (แนะนำใช้ใน After all)

Full Example

REF

--

--

PanachaiNY
PanachaiNY

Written by PanachaiNY

Architecture, Flutter, Golang, React, DevOps

No responses yet