Xét nghiệm kép? Chế nhạo? Sơ khai? Gián điệp? Giả mạo?

Tram Ho

Lời mở đầu

Một vấn đề mà khá nhiều lập trình viên mắc phải đó là sử dụng những thứ mà mình chưa hiểu rõ về nó. Mình cũng vậy. Dù đã viết khá nhiều UT cho các dự án khác nhau nhưng đến bây giờ mình vẫn cảm thấy khá là nhập nhằng giữa các khác niệm được nhắc đến ở tiêu đề bài viết này. Vậy là mình ngồi đây, tìm hiểu và cùng xem lại các khái niệm về UT này là gì và có những sự khác biệt gì giữa chúng. Ok. Let’s go!!!

Khái niệm

Chắc các bạn đã từng nghe trên một lần các khái niệm như test double, mock, stub, spy, fake trong một buổi sharing nào đấy. Hoặc thoáng qua trong một bài viết về chuyên môn. Nhưng tại sao chúng ta lại cần sử dụng chúng?
Đầu tiên ta nhắc lại kiến thức cũ một chút. Unit test là gì? Unit test là một phương pháp kiểm thử phần mềm trong đó các đoạn mã (code) được kiểm tra độc lập và cụ thể, từng phần riêng lẻ của chương trình (như hàm, phương thức, lớp) được kiểm thử để đảm bảo chức năng của nó hoạt động đúng như mong đợi.

Vậy nên Test double được sinh ra để sử dụng trong kiểm thử phần mềm để chỉ các đối tượng giả định được sử dụng để thay thế cho các thành phần phụ thuộc của một đơn vị thử nghiệm. Test double được sử dụng để cô lập đơn vị thử nghiệm khỏi các thành phần phụ thuộc mà không cần thực sự sử dụng các thành phần đó.

Có nhiều loại test double, trong đó “Test double” là thuật ngữ tổng quát để chỉ đến các loại sau: Mock, Stub, Spy, Fake.

Mock

Là một đối tượng giả định được sử dụng để kiểm tra xem một phương thức đã được gọi hay chưa, và nếu được gọi, phương thức đó được gọi với các tham số chính xác hay không.

Trong ví dụ này, chúng ta đang kiểm thử lớp Calculator bằng cách sử dụng một test double cho AdditionService, được thực hiện bằng cách sử dụng Mockito để tạo ra một đối tượng mock cho AdditionService. Chúng ta giả định rằng AdditionService sẽ trả về giá trị 5 khi được gọi với các tham số là 2 và 3, sau đó kiểm tra kết quả trả về của phương thức add trong lớp Calculator.
Chúng ta cũng kiểm tra xem phương thức add của AdditionService đã được gọi với đúng các tham số hay chưa bằng cách sử dụng phương thức verify của Mockito.

Stub

Là một đối tượng giả định được sử dụng để trả về giá trị cứng định trước cho một cuộc gọi phương thức cụ thể.

Trong ví dụ này, chúng ta đã sử dụng PaymentGatewayStub để cung cấp giá trị mặc định cho phương thức pay của PaymentGateway, để kiểm tra xem lớp Order đã in ra đúng thông báo khi thanh toán thành công hay không.

Spy

Là một đối tượng giả định được sử dụng để ghi lại thông tin về các cuộc gọi phương thức cụ thể, ví dụ như số lần gọi, các tham số được truyền vào và giá trị trả về.

Trong ví dụ này, chúng ta đã tạo ra một CalculatorSpy để giám sát việc gọi phương thức add của Calculator. Chúng ta đã ghi lại số lần phương thức này được gọi bằng cách sử dụng một biến đếm và kiểm tra giá trị trả về của phương thức add, cũng như số lần phương thức được gọi đến.

Fake

Các phương thức giả lập như stub, mock và spy đôi khi không đủ để kiểm tra các trường hợp phức tạp hoặc yêu cầu sử dụng một đối tượng thực sự để thực hiện các hành động phức tạp. Trong trường hợp này, bạn có thể sử dụng một đối tượng giả định là một đối tượng giả (fake object).

Là một đối tượng giả định được sử dụng để cung cấp một triển khai thay thế cho một thành phần phụ thuộc thực sự, giúp giảm thiểu các phụ thuộc đến các thành phần bên ngoài hoặc giảm thiểu sự phức tạp của việc thiết kế và triển khai.

Ở đây, chúng ta sử dụng một đối tượng giả UserDaoFake để thay thế cho đối tượng thực UserDaoImpl. Đối tượng UserDaoFake này chỉ đơn giản là lưu trữ các đối tượng User trong một bản đồ để có thể trả về một đối tượng User cụ thể khi phương thức getUser được gọi. Khi chúng ta kiểm tra phương thức isValidUser của lớp UserService, chúng ta sử dụng đối tượng UserDaoFake này để thực hiện việc lấy dữ liệu và kiểm tra kết quả trả về.

Tạm kết

Hi vọng qua bài viết này bạn đọc đã có cái nhìn rõ ràng hơn về các khái niệm đã nhắc đến trong tiêu đề. Chúc vui.

Chia sẻ bài viết ngay

Nguồn bài viết : Viblo