DI for test
kanthakran
Posted on December 6, 2020
บทความนี้เป็นบันทึกที่จดไว้เพื่อแชร์สิ่งที่รู้ลงไปถ้าผิดอะไรช่วยกันคอมเม้นไว้ได้นะครับ
วันนี้ผมมาในหัวข้อเรื่อง dependency injection แต่ก่อนหน้านี้หัวข้อมันคือ Structure สำหรับการ mock เพื่อ test ที่ชื่อหัวข้อแบบนี้เพราะคิดไม่ออก
สิ่งที่เราจะได้รับจากบทความนี้คือ Loose Coupling และ Dependency Injection มีความสำคัญกับการ mock เพื่อ test ยังไง ผมเป็นคนหนึ่งที่เคยพยามที่จะเขียน test ต่างๆ แต่ติดปัญหา
- function นี้เป็น private เราจะ test ยังไงควรเปลี่ยน pubilc สำหรับ test ไหม
- แล้วทำไมเราต้องทำ dependency injection ในเมื่อเราสามารถประกาศตัวแปลใช้ได้ตรงๆ ได้
โดย ผมจะไม่สนใจว่าการ test นี้จะเป็นการเทสแบบไหน unit หรือ integration เอาแค่ concept
สารบัญ
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
Tight Coupling
เป็นการสร้าง dependency ที่ผูกกันติดจนยากที่จะ mock userRepository getUserByStatus เพราะเกิดการ new ใน class
เผื่อมองภาพไม่ออก การที่ userRepository ถูก new ใน class userService มันทำให้เราเข้าไปแก้ไขอะไรในนั้นได้ยาก
Loose Coupling
จากตัวอย่างด้านบนถ้าเราเอา userRepository มาใส่ใน constructor เป็น parameter มันจะเกิดการ Loose coupling เพราะ userRepository ไม่ได้ขึ้นอยู่กับ class UserService การส่งสิ่งที่เราจะใช้ผ่าน constructor ถือเป็นการทำ Dependency injection ผ่าน constructor
ใน typescript เอา private ไปใส่ใน constructor มันจะกลายเป็น property ของ class เลย
สิ่งที่เกิดขึ้นคือ เราสามารถที่จะแก้ไข class userRepository ก่อนจะส่งเข้าไปได้
การ mock เพื่อ test
(mock คือการสร้างของจำลองไว้ test)
จากด้านบนเราจะเห็นแล้วว่าการที่เราจะ mock ของนั้นจะต้องมีโครงสร้างของโปรแกรมที่ดีพอที่จะทำให้เรา mock ได้ Loose Coupling
ตัวอย่างนี้จะใช้ jest นะครับ
ผม mock getCountUserByStatus ให้ return 20 มาเลย
ถ้าใน service มีการคำนวนอะไรเราก็จะสามารถ expect ค่านั้นได้เลย
สรุป
การ mock เพื่อ test นั้นจำเป็นต้องวางโครงสร้างของโปรแกรมให้ดีเพื่อที่การ mock เพื่อ test จะได้ทำได้ง่าย ไม่ว่าจะเป็นการแยก class ให้ดี หรือการทำ dependency injection ก็ตามถ้าเรา loose coupping ก็ไม่จำเป็นต้องเปลี่ยน function หรือ property เป็น public เพื่อเทส (เพราะมันไม่ควรทำ)
ผิดถูกยังไง comment ได้นะครับ
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
November 29, 2024