- การทดสอบหน่วย (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 คุณสามารถเขียนการทดสอบที่มีประสิทธิภาพซึ่งเพิ่มความเสถียรและความน่าเชื่อถือของการทำแอพของคุณ