- การทดสอบหน่วย (Unit Testing) ใน Spring Boot
- การสร้างแอปพลิเคชัน
- การเขียนแบบทดสอบหน่วย (Unit Test)
- การทดสอบการรวมระบบ (Integration Testing)ใน Spring Boot
- การเขียนแบบทดสอบการบูรณาการ (Integration Testing)
การทดสอบเป็นส่วนสำคัญของกระบวนการการทำแอพใดๆ ช่วยให้มั่นใจได้ว่าโค้ดทำงานตามที่คาดไว้และป้องกันการเกิดข้อบกพร่องหรือการถดถอย ใน Spring Boot ซึ่งเป็นเฟรมเวิร์กที่มีคุณลักษณะหลากหลายซึ่งสร้างขึ้นจากเฟรมเวิร์ก Spring การทดสอบจะได้รับความสำคัญอย่างมากและได้รับการสนับสนุนด้วยยูทิลิตี้และไลบรารีในตัวหลายตัว
ในบทความนี้ เราจะเจาะลึกการทดสอบใน Spring Boot โดยเน้นที่การทดสอบหน่วยและการทดสอบการรวมระบบ นอกจากนี้ เราจะสาธิตแนวคิดเหล่านี้ด้วยการทำแอพ Spring Boot อย่างง่าย และเขียนการทดสอบสำหรับแอปพลิเคชันนั้น
1. การทดสอบหน่วย (Unit Testing) ใน Spring Boot
การทดสอบหน่วยเป็นวิธีการทดสอบโดยแยกแต่ละหน่วยของซอร์สโค้ด เช่น เมธอดหรือคลาส ใน Spring Boot เรามักจะใช้ JUnit ซึ่งเป็นเฟรมเวิร์กการทดสอบหน่วยยอดนิยมใน Java ร่วมกับ Mockito ซึ่งเป็นเฟรมเวิร์กจำลองที่เราใช้ในการเขียนการทดสอบหน่วยสำหรับเลเยอร์ที่มีการขึ้นต่อกันของเลเยอร์อื่น
2. การสร้างแอปพลิเคชัน
มาทำแอพ Spring Boot อย่างง่ายเพื่อสาธิตการทดสอบหน่วย เราจะพัฒนาบริการ RESTful พื้นฐานด้วยคลาสUserService
ที่โต้ตอบกับฐานข้อมูลสมมุติโดยใช้อินเทอร์เฟซ UserRepository
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public List<User> getAllUsers() {
return userRepository.findAll();
}
}
เป็นอินเทอร์เฟซ UserRepository
ที่ขยาย Spring Data JPA’s JpaRepository
.
public interface UserRepository extends JpaRepository<User, Long> {}
3. การเขียนแบบทดสอบหน่วย (Unit Test)
สำหรับคลาส UserService
เราสนใจที่จะทดสอบวิธีการ getAllUsers
นี้ เราจะเขียนการทดสอบเพื่อให้แน่ใจว่าวิธีนี้จะส่งคืนรายชื่อผู้ใช้เมื่อเรียก
@RunWith(SpringRunner.class)
public class UserServiceTest {
@Mock
private UserRepository userRepository;
@InjectMocks
private UserService userService;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
@Test
public void testGetAllUsers() {
User user1 = new User(1L, "John Doe", "johndoe@example.com");
User user2 = new User(2L, "Jane Doe", "janedoe@example.com");
when(userRepository.findAll()).thenReturn(Arrays.asList(user1, user2));
List<User> result = userService.getAllUsers();
assertEquals(2, result.size());
verify(userRepository, times(1)).findAll();
}
}
ในการทดสอบนี้ เรากำลังจำลองอินเทอร์เฟซ UserRepository
เนื่องจากการทดสอบหน่วยไม่ควรอาศัยการเชื่อมต่อฐานข้อมูลจริง เราใช้คำอธิบายประกอบ @Mock
เพื่อสร้างวัตถุจำลองของคลาส UserRepository
และคำอธิบายประกอบ @InjectMocks
เพื่อใส่วัตถุจำลองลงในคลาส UserService
ในเมธอด testGetAllUsers
เราระบุลักษณะการทำงานของเมธอด userRepository.findAll()
เมื่อเรียกเมธอดโดยใช้when
เมธอดของ Mockito จากนั้นยืนยันว่าเมธอด userService.getAllUsers()
นั้นส่งคืนผลลัพธ์ที่คาดหวัง
4. การทดสอบการรวมระบบ (Integration Testing)ใน Spring Boot
ในขณะที่การทดสอบหน่วยตรวจสอบส่วนประกอบแต่ละรายการแยกกัน การทดสอบการรวมจะตรวจสอบว่าส่วนประกอบต่างๆ ของแอปพลิเคชันทำงานร่วมกันอย่างถูกต้อง เช่น การทำงานร่วมกันระหว่างตรรกะทางธุรกิจและชั้นฐานข้อมูล
ใน Spring Boot โดยทั่วไป เราจะใช้คำอธิบายประกอบ @SpringBootTest
เพื่อแสดงคลาสการทดสอบการรวมระบบ คำอธิบายประกอบนี้โหลดบริบท ของแอปพลิเคชันที่สมบูรณ์สำหรับการทดสอบ และมักจะรวมกับการตั้งค่าสภาพแวดล้อมเว็บผ่าน WebEnvironment.RANDOM_PORT
หรือ WebEnvironment.DEFINED_PORT
เราจะใช้ TestRestTemplate
ซึ่งเป็นทางเลือก RestTemplate
ที่เหมาะสำหรับการทดสอบการรวมระบบ
5. การเขียนแบบทดสอบการบูรณาการ (Integration Testing)
ในการสาธิต สมมติว่าเรามีคลาส UserController
ที่มีเมธอด getAllUsers
ที่แมปกับคำขอ GET
@RestController
@RequestMapping("/users")
public class UserController {
@Autowired
private UserService userService;
@GetMapping
public ResponseEntity<List<User>> getAllUsers() {
return new ResponseEntity<>(userService.getAllUsers(), HttpStatus.OK);
}
}
นี่คือวิธีที่เราสามารถเขียนการทดสอบการรวมสำหรับมัน:
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class UserControllerIntegrationTest {
@Autowired
private TestRestTemplate restTemplate;
@MockBean
private UserService userService;
@Test
public void testGetAllUsers() {
User user1 = new User(1L, "John Doe", "johndoe@example.com");
User user2 = new User(2L, "Jane Doe", "janedoe@example.com");
when(userService.getAllUsers()).thenReturn(Arrays.asList(user1, user2));
ResponseEntity<List> response = restTemplate.getForEntity("/users", List.class);
assertEquals(HttpStatus.OK, response.getStatusCode());
assertEquals(2, response.getBody().size());
}
}
ในการทดสอบด้านบน เรากำลัง TestRestTemplate
ใช้คำขอ GET และ UserService
ถูก mocked คำอธิบายประกอบ @MockBean
จะใช้แทนคำอธิบายประกอบ @Mock
ที่ใช้ในการทดสอบหน่วย คำอธิบายประกอบ @MockBean
จะเพิ่มวัตถุจำลองในบริบทของแอปพลิเคชัน Spring โดยแทนที่ bean ที่มีอยู่ที่เป็นประเภทเดียวกันในบริบท
ทั้งการทดสอบหน่วยและการทดสอบการรวมมีบทบาทสำคัญในการรักษาความสมบูรณ์ของโค้ดเบสในการทำแอพ ในขณะที่การทดสอบหน่วยช่วยให้มั่นใจว่าส่วนประกอบแต่ละส่วนทำงานได้ตามที่คาดไว้ การทดสอบการรวมระบบจะยืนยันว่าส่วนประกอบเหล่านี้ทำงานร่วมกันได้ดี เมื่อใช้การสนับสนุนการทดสอบในตัวของ Spring Boot คุณสามารถเขียนการทดสอบที่มีประสิทธิภาพซึ่งเพิ่มความเสถียรและความน่าเชื่อถือของการทำแอพของคุณ