Cách sử dụng Rspec Mocks
This post hasn't been updated for 6 years
Bài viết gốc Jesus Castello - How to Use RSpec Mocks
Mock trong Rspec là gì?
Mock là một đối tượng sử dụng để test.
Chúng ta dùng các mocks để test tương tác giữa hai đối tượng.
Vd: Viết một API để lật ảnh
Thay vì tự viết code thao tác ảnh có thể sử dụng gem mini_magick
.
Khi muốn test tương tác giữa code và thư viện bên ngoài thì sẽ viết một mock với kỳ vọng rằng các phương thức được gọi với class ImageProcessor
.
Có nghĩa là chúng ta sẽ không lật các ảnh(thao tác chậm) mỗi khi chúng ta chạy test.
Hoạt động bằng cách nào?
Mocks thay thế đối tượng gốc vậy phương thức thật sẽ không bao giờ được gọi. Hãy xem ví dụ dưới này.
Ví dụ Rspec mock
Đây là test ImageFlipper
Bây giờ nếu chạy test chúng ta có thể viết code với TDD style.
Đầu tiên chúng ta cần viết một class ImageFipper
với phương thức flip
như dưới:
Sau khi chạy test chúng ta nhận được phản hồi từ Rspec
Phản hồi trên chỉ rằng phương thức trên gọi 0 lần nhưng kỳ vọng được gọi 1 lần.
Chúng ta có thể làm cho test qua được bằng cho gì nó cần:
Tiếp đến chúng ta qua được test:
Ở đây chúng ta đã làm gì?
Chúng ta đã tạo một class mà cho phép class image_processor
đáp ứng với phương thức flip
.
Ví dụ này là cơ bản nhưng chúng ta có thể tưởng tượng một thao tác hoàn thiện của ImageFlipper
để kiểm tả nếu như file có tồn tại không, ảnh có hợp lệ không, vv....
Trong một test thông thương chúng ta kiểm tra kết quả trả về của phương thức
Liệu phương thức này trả về một ảnh đã lật?
Khi sử dụng mock chúng ta test hành vi
Chúng ta đã cho các thứ làm việc đúng với thông tin đúng và chính xác với lượng thời gian mà chúng ta cần?
Mocks vs Stubs
Một điểm nhầm lẫn là so sánh giữa mocks và stubs.
Có gì khác nhau?
- stub chỉ là phương thức với đáp ứng biết trước, nó không quan tâm về hành vi.
- mock kỳ vọng phương thức sẽ được gọi nếu họ không được gọi test sẽ thất bại.
Đây là một stub trong Rspec
Phương thức allow
là thứ làm trở thành stub.
Chúng ta cho phép đối tượng đang test double "json"
nhận và đáp ứng với phương thước này nhưng chúng ta không kiểm trả là nó đã được gọi. Đây là điểm khác nhau!
Làm thế nào để sử dụng Verified Doubles
Một nhược điểm của mocks và stubs là chúng ta có thể gặp trường hợp sẽ dụng một phương thức mà không tồn tại trong code production.
Bởi vì tên phương thức đã thay đổi hoặc do lỗi đánh máy!
Verified doubles
Một verified double có thể sử dụng là một sub allow
hoặc một mock expect
và nó sẽ kiểm trả rằng một phương thức với tên đó tồn tại.
Ví dụ:
mock = instance_double(ImageProcessor)
Nó sẽ nêu lỗi nếu phương thức không tồn tại nhưng nó sẽ hoạt động đúng nếu phương thức tồn tại.
Mocks trả về các giá trị
Ta trở về mocking với ví dụ cuối cùng ta có:
Khi code gọi flip
mock sẽ trả về nil
. Nếu code mong muốn trả về giá trị khác nil
thì kết quả sẽ là một lỗi.
Chúng ta có thể khắc phục bằng cách mock và trả về một kết quả như dưới
Làm thế nào để Mock các phương thức tức thời(Instance methods)
Giả thiết chúng ta có code như này
Với phương thức này rất khó để test do ngẫu nhiên.
Rspec cho phép chúng ta mock hoặc stub rand
như sau:
rand
trả về một giá trị cố định vậy chúng ta có thể dùng nó để test kết quả phương thức của chúng ta.
Khi nào sử dụng Mocks?
Khi nào chúng ta nên sử dụng mocks? Phát triển phần mềm là một đề tài phức tạp. Nhưng dưới đây là một số hướng dẫn có thể làm theo
- Nếu phương thức đang test trả về một gía trị và không có tác dụng phụ(tạo các file, tạo API request,v..) thì chúng ta không cần mock. Chỉ cần kiểm tra giá trị trả về.
- Nếu phương thức làm việc và gửi các yêu cầu đến với các đối tượng ngoài thì chúng ta có thể mock tương tác với các đối tượng đó.
- Nếu phương thức là
Yêu cầu
dữ liệu từ dịch vụ bên ngoài(API) thì chúng ta có thể sử dụng stab để cùng cấp dữ liệu phụ vụ mục đích test.
Cuối cùng Đừng mock các class ứng dụng của minh
!
Tại sao? Bởi vì điều đó thúc đẩy việc kết hợp các thử nghiệm với các triển khai chi tiết và nó làm cho code khó thay đổi hơn.
Kết luận
Bài viết đã mô tả về Rspec mocks, stubs và verified doubles. Hy vọng bài này sẽ mang lợi ích cho các bạn đang đọc.
Tham khảo
All Rights Reserved