Computer >> Máy Tính >  >> Lập trình >> Ruby

Cách sử dụng RSpec Mocks (Hướng dẫn từng bước)

Mô hình trong RSpec là gì?

(Hoặc một mô hình nói chung, bởi vì đây không phải là một khái niệm dành riêng cho RSpec.)

Mô hình là một đối tượng được sử dụng để thử nghiệm .

Bạn sử dụng mocks để kiểm tra sự tương tác giữa hai đối tượng. Thay vì kiểm tra giá trị đầu ra, giống như trong một kỳ vọng thông thường.

Ví dụ :

Bạn đang viết một API để lật hình ảnh.

Thay vì viết mã thao tác hình ảnh của riêng bạn, bạn sử dụng đá quý như mini_magick .

Bạn muốn kiểm tra sự tương tác giữa mã của mình và phụ thuộc bên ngoài này … Vì vậy bạn viết một mô hình mong đợi các phương thức chính xác được gọi trên ImageProcessor lớp học.

Điều này có nghĩa là bạn sẽ không bị lật hình ảnh (hoạt động chậm) mỗi khi bạn chạy thử nghiệm của mình.

Điều đó hoạt động như thế nào?

Mô hình thay thế đối tượng ban đầu, vì vậy các phương thức thực sẽ không được gọi.

Đã đến lúc cho một số ví dụ về mã!

Ví dụ về RSpec Mock

Đây là ImageFlipper kiểm tra:

 RSpec.describe "ImageFlipper" do it "gọi phương thức lật với các đối số chính xác" do mock =double ("mini_magick") mong đợi (mock) .to accept (:flip) .with ("ruby.jpg") img =ImageFlipper.new (mock) img.flip ("ruby.jpg") endend 

Với thử nghiệm này, chúng tôi có thể viết mã của mình bằng TDD.

Đầu tiên :

Chúng ta cần viết một ImageFlipper lớp học.

Như thế này :

 class ImageFlipper def khởi tạo (image_processor) @image_processor =image_processor endend 

Chúng tôi cũng cần một flip phương pháp:

 def flip (file_name) end 

Bây giờ chúng tôi nhận được phản hồi này từ RSpec:

 Failures:1) ImageFlipper gọi phương thức flip với các đối số chính xác Thất bại / Lỗi:mong đợi (mô hình) .to accept (:flip) .with ("ruby.jpg") (Double "mini_magick"). flip (" ruby.jpg ") dự kiến:1 lần với đối số:(" ruby.jpg ") đã nhận:0 lần # ./rspec-mocks.rb:6:in` khối (2 cấp) trong  '

Điều này nói lên rằng flip phương thức được gọi 0 lần, nhưng nó được mong đợi được gọi 1 lần.

Bạn có thể làm cho bài kiểm tra này vượt qua bằng cách cung cấp cho nó những gì nó muốn :

 def flip (file_name) @ image_processor.flip (file_name) end 

Và bạn hiểu rồi, chúng tôi có một bài kiểm tra vượt qua :

. Hoàn thành trong 0,00751 giây (tệp mất 0,11157 giây để tải) 1 ví dụ, 0 lỗi 

Hãy xem lại:Chúng ta đã làm gì ở đây?

Chúng tôi đã tạo một ImageFlipper lớp nhận image_processor .

Bộ xử lý này phản hồi với flip phương pháp.

Chúng tôi sử dụng một mô hình để kiểm tra xem phương thức này có được gọi một lần hay không, với một đối số.

Tôi biết.

Ví dụ này đơn giản.

Nhưng bạn có thể tưởng tượng việc triển khai hoàn chỉnh ImageFlipper kiểm tra xem tệp có tồn tại hay không, nếu đó là hình ảnh hợp lệ, v.v.

Sự khác biệt giữa Thử nghiệm giả mạo &Giá trị

Trong một bài kiểm tra thông thường, bạn kiểm tra giá trị trả về của một phương thức :

“Phương thức này có trả về hình ảnh bị lật không?”

Khi sử dụng mô hình bạn đang kiểm tra hành vi :

“Chúng ta có nói cho người khác biết điều phải làm, với thông tin phù hợp và chính xác số lần chúng ta cần không?”

Mô hình so với Stubs

Một điểm nhầm lẫn khác là về việc so sánh mô-típ và sơ khai.

Sự khác biệt là gì?

  • Sơ khai chỉ là một phương pháp có phản hồi soạn trước, nó không quan tâm đến hành vi.
  • Mô phỏng mong đợi các phương thức được gọi, nếu chúng không được gọi thì bài kiểm tra sẽ thất bại.

Đây là sơ khai về RSpec :

 ste =double ("json") allow (ste) .to accept (:response) do {"blog" => "rubyguides.com", "rating" => "5/5"}. to_jsonend  

allow phương pháp là thứ làm cho điều này còn sơ khai.

Chúng tôi đang cho phép đối tượng thử nghiệm của mình double("json") để nhận và phản hồi phương thức này, nhưng chúng tôi không kiểm tra xem nó có được gọi không .

Đó là sự khác biệt!

Cách sử dụng Bộ đôi đã xác minh

Một trong những nhược điểm của chế độ giả &sơ khai là bạn có thể sử dụng một phương pháp không tồn tại trong mã sản xuất của bạn.

Vì tên phương thức đã thay đổi… hoặc có thể bạn đã mắc lỗi chính tả!

Gặp gỡ đôi đã được xác minh .

Một đôi đã xác minh có thể được sử dụng như một bản gốc (allow ) hoặc một mô hình (expect ) &nó sẽ kiểm tra xem có tồn tại một phương thức có tên này không.

Ví dụ :

 mock =instance_double (ImageProcessor) 

Điều này sẽ gây ra lỗi nếu phương thức không tồn tại:

 1) ImageFlipper gọi phương thức flip với các đối số chính xác Thất bại / Lỗi:hope (mock) .to accept (:flip) .with ("ruby.jpg") lớp ImageProcessor không triển khai phương thức instance:flip 

Nhưng nó sẽ hoạt động chính xác nếu phương thức tồn tại.

Mô phỏng các giá trị trả lại

Hãy quay lại chế nhạo.

Trong ví dụ cuối cùng chúng tôi đã có cái này:

 mong đợi (giả lập) .to nhận (:lật) .with ("ruby.jpg") 

Khi mã của bạn gọi đến flip , mô hình sẽ trả về nil .

Nếu mã đang mong đợi một số giá trị khác với nil thì điều này sẽ dẫn đến lỗi.

Bạn có thể sửa lỗi này bằng cách làm cho mô hình trả về một kết quả.

Như thế này :

 mong đợi (giả lập) .to accept (:flip) .with ("ruby.jpg"). and_return ("ruby-flip.jpg") 

Cách giả lập phương thức phiên bản

Giả sử bạn có mã như sau:

 class NumberGenerator xác định ngẫu nhiên "A" * rand (1..10) endend 

Phương pháp này khó kiểm tra vì tính ngẫu nhiên.

RSpec cho phép bạn mô phỏng hoặc khai thác rand .

Như thế này :

 nó "tạo ra một số ngẫu nhiên" do máy phát điện =NumberGenerator.new allow (máy phát điện) .to nhận (:rand) .and_return (5) mong đợi (máy phát điện.random) .to eq ("AAAAA") kết thúc 

Bây giờ :

rand trả về một giá trị cố định để bạn có thể sử dụng nó để kiểm tra kết quả của phương pháp của mình.

Lý tưởng nhất là bạn muốn thêm phần phụ thuộc của mình (rand , trong trường hợp này) để bạn có thể kiểm soát nó. Chèn một phần phụ thuộc có nghĩa là bạn chuyển nó vào dưới dạng một tham số , không có gì lạ mắt.

Nhưng đôi khi chỉ cần khai báo phương pháp sẽ thuận tiện hơn.

Khi nào thì sử dụng Mocks?

Bây giờ cho câu hỏi LỚN…

Chính xác thì khi nào bạn nên sử dụng mocks?

Phát triển phần mềm là một chủ đề phức tạp.

Nhưng có một số nguyên tắc bạn có thể làm theo :

  1. Nếu phương thức đang được thử nghiệm trả về một giá trị và nó không có tác dụng phụ (tạo tệp, thực hiện yêu cầu API, v.v.) thì bạn không cần mô hình. Chỉ cần kiểm tra giá trị trả lại.
  2. Nếu phương pháp đang hoạt động với các đối tượng bên ngoài và gửi lệnh cho chúng, thì bạn có thể mô phỏng các tương tác với các đối tượng này.
  3. Nếu phương pháp đang YÊU CẦU dữ liệu từ một dịch vụ bên ngoài (như API), thì bạn có thể sử dụng phần sơ khai để cung cấp dữ liệu này cho mục đích thử nghiệm.

Bạn muốn đặt trước chế độ chế nhạo cho các tương tác với thế giới bên ngoài .

Nói cách khác…

Tránh chế nhạo các lớp ứng dụng của chính bạn!

Tại sao?

Vì điều đó thúc đẩy việc kết hợp các thử nghiệm của bạn với chi tiết triển khai & điều đó khiến mã của bạn khó thay đổi hơn .

Ngoại lệ duy nhất dành cho các lớp là trình bao bọc cho mã của bên thứ ba.

Xem video này để tìm hiểu thêm :

Tóm tắt

Bạn đã tìm hiểu về RSpec mocks, sơ khai và các bộ đôi đã được xác minh!

Hãy chia sẻ bài viết này để nhiều người có thể tận hưởng và hưởng lợi từ nội dung này.

Cảm ơn vì đã đọc 🙂