DI for test

gun27311

kanthakran

Posted on December 6, 2020

DI for test

บทความนี้เป็นบันทึกที่จดไว้เพื่อแชร์สิ่งที่รู้ลงไปถ้าผิดอะไรช่วยกันคอมเม้นไว้ได้นะครับ

วันนี้ผมมาในหัวข้อเรื่อง dependency injection แต่ก่อนหน้านี้หัวข้อมันคือ Structure สำหรับการ mock เพื่อ test ที่ชื่อหัวข้อแบบนี้เพราะคิดไม่ออก

สิ่งที่เราจะได้รับจากบทความนี้คือ Loose Coupling และ Dependency Injection มีความสำคัญกับการ mock เพื่อ test ยังไง ผมเป็นคนหนึ่งที่เคยพยามที่จะเขียน test ต่างๆ แต่ติดปัญหา

  • function นี้เป็น private เราจะ test ยังไงควรเปลี่ยน pubilc สำหรับ test ไหม
  • แล้วทำไมเราต้องทำ dependency injection ในเมื่อเราสามารถประกาศตัวแปลใช้ได้ตรงๆ ได้

โดย ผมจะไม่สนใจว่าการ test นี้จะเป็นการเทสแบบไหน unit หรือ integration เอาแค่ concept

สารบัญ

  1. เกรินนำ
  2. Tight Coupling
  3. Loose Coupling & Dependency injection
  4. การ mock เพื่อ automate test
  5. สรุป

Loose coupling และ Dependency injection คืออะไร

Loose coupling คือถ้าเราไปแปลใน google มันจะแปลว่า "ข้อต่อหลวม" มันคือการเขียนโปรแกรมให้ dependency ของ class หลุดออกจากกันเพื่อ mock data เช่น

โจทย์

ถ้าผมอยากจะเขียน api get User by status
http method : GET
path : /user/status
ผมต้องการ การ get user by status จาก database
สิ่งที่ผมวางไว้คือ userRepository คือตัวจัดการเอาของออกจาก database
ส่วน userService คือตัวที่จะนำมาคำนวนต่างๆ (ตัวอย่างขอไม่มีการคำนวน)

project structure

Alt Text

Tight Coupling

เป็นการสร้าง dependency ที่ผูกกันติดจนยากที่จะ mock userRepository getUserByStatus เพราะเกิดการ new ใน class
Alt Text

เผื่อมองภาพไม่ออก การที่ userRepository ถูก new ใน class userService มันทำให้เราเข้าไปแก้ไขอะไรในนั้นได้ยาก
Alt Text

Loose Coupling

จากตัวอย่างด้านบนถ้าเราเอา userRepository มาใส่ใน constructor เป็น parameter มันจะเกิดการ Loose coupling เพราะ userRepository ไม่ได้ขึ้นอยู่กับ class UserService การส่งสิ่งที่เราจะใช้ผ่าน constructor ถือเป็นการทำ Dependency injection ผ่าน constructor

ใน typescript เอา private ไปใส่ใน constructor มันจะกลายเป็น <br>
property ของ class
ใน typescript เอา private ไปใส่ใน constructor มันจะกลายเป็น property ของ class เลย

Alt Text
สิ่งที่เกิดขึ้นคือ เราสามารถที่จะแก้ไข class userRepository ก่อนจะส่งเข้าไปได้

การ mock เพื่อ test

(mock คือการสร้างของจำลองไว้ test)
จากด้านบนเราจะเห็นแล้วว่าการที่เราจะ mock ของนั้นจะต้องมีโครงสร้างของโปรแกรมที่ดีพอที่จะทำให้เรา mock ได้ Loose Coupling

Alt Text

ตัวอย่างนี้จะใช้ jest นะครับ
Alt Text
ผม mock getCountUserByStatus ให้ return 20 มาเลย
ถ้าใน service มีการคำนวนอะไรเราก็จะสามารถ expect ค่านั้นได้เลย

สรุป

การ mock เพื่อ test นั้นจำเป็นต้องวางโครงสร้างของโปรแกรมให้ดีเพื่อที่การ mock เพื่อ test จะได้ทำได้ง่าย ไม่ว่าจะเป็นการแยก class ให้ดี หรือการทำ dependency injection ก็ตามถ้าเรา loose coupping ก็ไม่จำเป็นต้องเปลี่ยน function หรือ property เป็น public เพื่อเทส (เพราะมันไม่ควรทำ)

ผิดถูกยังไง comment ได้นะครับ

💖 💪 🙅 🚩
gun27311
kanthakran

Posted on December 6, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related