Restful Spring-Boot + Unit Test Part 1
Spring Initializr , Entity , Repository and Unit Test
Requirements
ทั้ง JDK , Build tools ( Gradle , Maven ) ต้องการ Set Path ด้วย
สำหรับเพื่อนๆที่ต้องการความสบายในการติดตั้ง เจ้าของบทความแนะนำให้ใช้ IDE เป็น VSCode แล้วติดตั้ง Extension Pack for Java , Spring Boot Tools
หลังติดตั้ง Extension แล้ว สามารถกด Ctrl + Shift + P -> Java: Install New JDK เพื่อติดตั้ง JDK ได้ใน VSCode เลย
Task
ทาง Manager ต้องการสร้าง Landing Page ที่จะแสดงสินค้าของทางบริษัท แต่สินค้าของบริษัทมีการเปลี่ยนแปลงบ่อย ไม่สะดวกที่จะใช้แบบ Static จึงมอบหมายให้ทีม Backend สร้าง API ตามนี้
- GET : แสดง Product ทั้งหมด
- CREATE : สร้าง Product ใหม่
- EDIT : แก้ไข Product By ID
- DELEET : ลบ Product BY ID
- GET : ค้นหา Product BY ID
- GET : ค้นหา Product ด้วย Product name
โดยแต่ละ Product จะมี
- Product name : ชื่อของ Product
- Price : ราคาของ Product
- Describe : รายละเอียดของ Product
Spring Initializr
ถ้าเพื่อนๆคุ้นเคยกับ Framework จะทราบดีว่า การจะเริ่มสร้าง Project ซัก Project หนึ่ง เป็นเรื่องที่เสียเวลาอย่างมาก Framework ส่วนใหญ่จึงมีตัว Initializr ให้ (อย่าง React ก็เป็น create-react-app )
เริ่มจากเข้าไปที่ Spring Initializr
Dependencies
เพื่อให้ Spring Boot สามารถทำ Task ตามที่ต้องการได้ จึงต้องติดตั้ง Dependencies เพิ่มเติม
สำหรับ Project แรก สามารถติดตั้งตามเจ้าของบทความได้เลย
- Spring Web : จะทำ Restful API จะขาดตัวนี้ไม่ได้เลย
- H2 : เป็น Database Default ของ Spring ไม่ต้อง Config อะไรเพิ่มเติม
- JPA : เป็น Quary พื้นฐานให้เรียกใช้ จะอธิบายละเอียดในบทความ
- DevTools : เจ้าของบทความใช้ในฐานะ Live Reload เท่านั้น
- Lombok : ใครเคยไม่ชอบ Java เพราะต้องมานั่งเขียน getter setter ต้องถูกใจ บอกลาการเขียน Object ที่มี Attibute 10 ตัว แต่มี getter setter รวมกันเกิน 50 Line
จากนั้นสามารถ Generate แล้วนำมาเปิดด้วย IDE ได้เลย ซึ่งเปิดครั้งแรกจะนานหน่อย เพราะ IDE จะพยายาม Download มาทั้งตัว Wrapper และ Dependencies
หลังจาก Open Project ไปที่ DemoApplication แล้วกดลูกศรเขียวดังภาพ
Boilerplate code
มาพักครึ่งทางกับคำศัพท์ที่เพื่อนๆน่าจะเจอบ่อยๆซักหน่อย เพื่อนๆอาจสงสัยว่า Lombok มีไว้เพื่อลด “Boilerplate Code”
คำว่า “Boilerplate Code” หมายถึงอะไรกันนะ
boilerplate code, or simply boilerplate, are sections of code that are repeated in multiple places with little to no variation
Boilder Plate หมายถึงโค๊ตที่ถูกเขียนซ้ำๆในหลายๆที่โดยที่ทำงานใกล้เคียงกัน
Entity
An entity is a lightweight persistence domain object. Typically, an entity represents a table in a relational database.
- ว่าง่ายๆ Entity คือ Object ที่เป็นตัวแทนของ Table ใน Database
- ถ้าใน Database มี Table ใด ถ้าเราจะติดต่อกับ Database นั้น ต้องมี Entity เดียวกับ Database นั้น
- Entity Annotation : Class นี้คือ Entity
- ID Annotaion : Field นี้คือ ID ซึ่งเป็น ID เดียวกับ Database
Repository
The goal of Spring Data repository abstraction is to significantly reduce the amount of boilerplate code required to implement data access layers for various persistence stores.
เพื่อนๆที่คุ้นเคยกับ Backend คงรู้จักกับ CRUD( Create , Read , Update , Date ) อยู่แล้วใช่ไหม? เพื่อนๆเคยคิดรึเปล่าว่า ไม่ว่าจะ Project ใดๆ แทบจะมีคุณสมบัติพื้นฐานของ CRUD เสมอ
เพื่อลด Boilerplate Code ทาง Spring boot จึงพัฒนา Repository ขึ้น
- Repository Annotation : Class นี้คือ Repository
- Long ใน JpaRepository คือ Type ของ ID Annotation ใน Entity
เพียงแค่ Extends JpaRepository เราก็ได้ Create , Find All มาแล้ว
Unit Test
Unit testing ensures that all code meets quality standards before it’s deployed
เพื่อนๆมั่นใจได้ 100% ว่าแต่ละ Line ที่เพื่อนๆโค๊ตลงไป ทำงานตามที่เพื่อนๆคิดไว้ ใน Project ที่ใหญ่ขึ้นไป อาจจะเป็นไปไม่ได้ที่เราจะทดสอบทุกกรณีที่เป็นไปได้ในโปรแกรม
แล้วถ้าวันหนึ่ง เราต้องการ Update Feature ของเราขึ้นมา เราจะมั่นใจได้อย่างไรว่า Code ที่เคยถูกต้องนั้น ยังจะทำงานถูกต้องอยู่
เพราะแบบนี้ เราจึงต้องการ Automated Testing และ Autometed Testing ที่สามารถทำได้ง่ายที่สุดคือ
Unit Test
อนึ่ง Spring ได้เตรียม Unit Test ดีๆอย่าง Junit มาให้ใช้ โดยไม่ต้องติดตั้ง dependency เพิ่มเติม
Repository Unit Test
การเขียน Unit Test จะแบ่งเป็น 3 ส่วนเสมอ ในที่นี้จะสร้าง Unit Test สำหรับ findAll
- given : ก่อน Test จะ Assign อะไรบ้าง
- when : ต้องการทดสอบอะไร( ในที่นี้คือ findAll Function ) ผลลัพท์เก็บไว้ใน Result
- then ตรวจสอบ Result ว่าเป็นไปตามที่คาดการณ์ไหม
ในเมื่อ save product 3 unit เมื่อ findAll จึงควรจะได้รับ Result เป็น List<Product> Size เท่ากับ 3 ซึ่งเป็นไปตามที่คาดการณ์ไว้
สังเกตว่า เราสามารถใช้ save , findAll ของ ProductRepository ได้ โดยที่ไม่จำเป็นต้อง Implement เองเลย
ที่ต้องรู้คือ สำหรับ DataJpaTest Annotation จะไม่ไป Save ใน database จริงๆ แต่จะ rollback หลังจากที่ Test เสร็จแล้ว
สำหรับเพื่อนๆที่อาจจะตามไม่ทัน หรือเขียนตามแล้วเกิดปัญหา สามารถไปดู Code ที่เจ้าของบทความเขียนได้ที่ Github
ส่งท้าย
ก่อนหน้านี้ เจ้าของบทความเป็นติ่ง JavaScript ทั้ง React & NodeJS แต่ได้รับโอกาศในการเข้าค่าย Java Software Engineering Bootcamp ที่ทาง KBTG เป็น Sponser
ต้องบอกว่า เจ้าของบทความไม่ชอบในตัว JavaScript หลายๆอย่าง
- ตัวแปรที่ไม่มี Type เสี่ยงต่อการเขียนให้ Bug มาก แล้วแก้ไขได้ยาก
- Framework อย่าง ExpressJs ต้องการ Library เสริมอีกไม่รู้กี่ตัว มีหลายๆตัวหน้าที่เหมือนกัน แต่คนละ Library ก็เยอะ ทำให้ตัดสินใจได้ยากว่าจะใช้อันไหน
- Testing สามารถทำได้ยาก // หลายคนเขียน JS แบบไม่ Test เลยก็เยอะ
แต่เมื่อมาเรียน Spring จะไม่เจอปัญหาเหล่านี้เลย ตัว Spring เองแทบจะจัดเตรียมทุกอย่างให้เราใน Framework อยู่แล้ว แถมการเขียน Unit Test เป็น default ของการ Develop คือแค่ init ก็มี test folder มายัดมือแล้ว
สุดท้ายก็ขอขอบคุณผู้อ่านทุกๆท่าน ที่อ่านมาถึงตรงนี้ หรือจะ Skip มาตรงนี้เลยก็ตาม ถ้ามีตรงไหนไม่เข้าใจ มีข้อติชมอะไร สามารถมาที่ Page AstralAria นะครับ
ในตอนจบบทความ เราจะสามารถ create , findAll ใน database ได้แล้ว ในบทความหน้า เราจะมาเติม edit , delete , findBy รวมไปถึงพัฒนา restful ของเรา ให้สามารถใช้งานได้จริงๆ ผ่าน API กันครับ
พบกันใหม่ในบทความ Restful Spring-Boot + Unit Test Part 2 ครับ