Trong phát triển phần mềm, việc viết test là một bước quan trọng để đảm bảo rằng ứng dụng hoạt động đúng như mong đợi, và đảm bảo được việc khi một chức năng mới được hoàn thành không ảnh hưởng đến chức năng cũ.
Trong bài viết này sẽ giới thiệu về 2 loại test là unit test và integration test mục đích và cách thực hiện của chúng trong Spring Boot.
1. Unit Test
Unit Test là gì?
Unit test là quá trình kiểm thử các thành phần nhỏ nhất của hệ thống, thường là các method trong các class. Mục tiêu của unit test là kiểm tra tính đúng đắn ủa từng method trong hệ thống mà không bị phụ thuộc bởi các thành phần khác.
Cách thực hiện Unit Test
Trong Spring Boot, unit test thường được thực hiện bằng cách sử dụng các framework như JUnit và Mockito. JUnit cho phép chúng ta viết các bài test, trong khi Mockito giúp tạo ra các giả lập(mock) để thay thế các phụ thuộc(dependency) thực sự trong quá trình test.
Ví dụ, để test một method trong một service chúng ta có thể viết unit test như sau:
Public class MyService {
@autowired
private MyRepository myRepository;
public MyEntity findById(long id) {
return myRepository.findById(id);
}
}
@RunWith(SpringRunner.class)
@SpringBootTest
public class MyServiceTest {
@Mock
private MyRepository myRepository;
@InjectMocks
private MyService myService;
@Test
public void testMethod() {
// Thiết lập dữ liệu giả lập
when(myRepository.findById(1L)).thenReturn(Optional.of(new MyEntity(1L, "Test")));
// Gọi phương thức cần kiểm thử
MyEntity result = myService.findById(1L);
// Kiểm tra kết quả
assertEquals("Test", result.getName());
}
}
Trong ví dụ trên, chúng ta thực hiện:
- @Mock MyRepository: giả lập một đối tượng MyRepository. Điều này giúp cho việc kiểm soát đối tượng và định nghĩa cách hoạt động của nó trong unit test
- @InjectMocks MyService: thực hiện inject mock(MyRepository) vào MyService
- testMethod
- đầu tiên chúng ta định nghĩa hàng vi của phương thức findById của MyRepository được gọi với tham số đầu vào là 1L
- MyEntity result = myService.findById(1L): gọi phương thức cần test findById
- assertEquals(“Test”, result.getName()): kiểm tra kết quả, nếu kết quả trả về sau khi call method khớp với giá trị expect là pass unit test.
Phân biệt Mock và MockBean
Trong Spring boot, @Mock và @MockBean là hai cách khác nhau để tạo mock cho các thành phần trong quá trình viết unit test.
- @Mock: Sử dụng để tạo các mock object phụ thuộc trong service được test. Khi sử dụng @Mock, cần phải khởi tạo Mockito bằng cách sử dụng @RunWith(MockitoJUnitRunner.class) hoặc trong method @Before khai báo MockitoAnnotations.initMocks(this);
@RunWith(MockitoJUnitRunner.class)
public class MyServiceTest {
@Mock
private MyRepository myRepository;
@InjectMocks
private MyService myService;
@Test
public void testMethod() {
// Thiết lập dữ liệu giả lập
when(myRepository.findById(1L)).thenReturn(Optional.of(new MyEntity(1L, "Test")));
// Gọi phương thức cần kiểm thử
MyEntity result = myService.findById(1L);
// Kiểm tra kết quả
assertEquals("Test", result.getName());
}
}
- @MockBean: sử dụng để tạo các object mock, thường được sử dụng trong integration test. Ví dụ trong các case integration test không thể thực hiện method để trigger đến bên thứ 3 như (AWS,…) chúng ta sẽ sử dụng @MockBean
@RunWith(SpringRunner.class)
@SpringBootTest
public class MyControllerIntegrationTest {
@MockBean
private AWSService awsService;
@Autowired
private TestRestTemplate restTemplate;
@Test
public void testGetEndpoint() {
// Thiết lập dữ liệu giả lập
when(awsService.uploadImageToS3()).thenReturn("image/path");
// Gửi yêu cầu GET đến endpoint
ResponseEntity<MyResponse> response = restTemplate.getForEntity("/api/my-endpoint", MyResponse.class);
// Kiểm tra kết quả
assertEquals(HttpStatus.OK, response.getStatusCode());
assertEquals("Expected Response", response.getBody().getMessage());
}
}
2. Integration Test
Integration Test là gì?
Integration test là quá trình test các thành phần liên quan kết hợp với nhau, bao gồm việc test thành phần giao tieeos với Database, các service khác. Mục đích của integration test là đảm bảo cho các thành phần hoạt động đúng khi integrate với nhau.
Cách triển khai Integration Test
Trong Spring Boot, Integration Test thường được thực hiện bằng cách sử dụng Spring’s testing support, cho phép chúng ta khởi động một ngữ cảnh ứng dụng (application context) đầy đủ và kiểm thử các thành phần trong ngữ cảnh đó.
Ví dụ, để kiểm thử một Controller trong Spring Boot, chúng ta có thể viết một bài Integration Test như sau:
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class MyControllerIntegrationTest {
@Autowired
private TestRestTemplate restTemplate;
@Test
public void testGetEndpoint() {
// Gửi yêu cầu GET đến endpoint
ResponseEntity<MyResponse> response = restTemplate.getForEntity("/api/my-endpoint", MyResponse.class);
// Kiểm tra kết quả
assertEquals(HttpStatus.OK, response.getStatusCode());
assertEquals("Expected Response", response.getBody().getMessage());
}
}
Kết luận
Unit Test và Integration Test đều là các phần quan trọng trong quá trình phát triển phần mềm. Unit Test giúp kiểm tra tính đúng đắn của từng phần nhỏ, trong khi Integration Test đảm bảo rằng các thành phần hoạt động đúng khi kết hợp với nhau. Sử dụng cả hai loại kiểm thử này trong Spring Boot sẽ giúp đảm bảo rằng ứng dụng của bạn hoạt động ổn định và đúng như mong đợi.